@oneuptime/common 11.7.2 → 11.7.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/KubernetesCostAllocation.ts +103 -0
- package/Models/DatabaseModels/AlertEpisodeStateTimeline.ts +1 -0
- package/Models/DatabaseModels/AlertStateTimeline.ts +1 -0
- package/Models/DatabaseModels/IncidentEpisodeStateTimeline.ts +1 -0
- package/Models/DatabaseModels/IncidentStateTimeline.ts +1 -0
- package/Models/DatabaseModels/Index.ts +5 -0
- package/Models/DatabaseModels/LogDropFilter.ts +89 -0
- package/Models/DatabaseModels/NetworkDeviceDiscoveryScan.ts +13 -3
- package/Models/DatabaseModels/RecommendationDismissal.ts +463 -0
- package/Models/DatabaseModels/ScheduledMaintenanceStateTimeline.ts +1 -0
- package/Models/DatabaseModels/StatusPageGroup.ts +95 -0
- package/Models/DatabaseModels/TableView.ts +40 -0
- package/Models/DatabaseModels/TraceDropFilter.ts +89 -0
- package/Models/DatabaseModels/WorkflowVariable.ts +5 -1
- package/Server/API/AlertAPI.ts +32 -17
- package/Server/API/BaseAPI.ts +31 -2
- package/Server/API/BaseAnalyticsAPI.ts +36 -2
- package/Server/API/CommonAPI.ts +57 -0
- package/Server/API/IncidentAPI.ts +60 -33
- package/Server/API/IncidentEpisodeAPI.ts +31 -16
- package/Server/API/MonitorAPI.ts +30 -0
- package/Server/API/MonitorTemplateAPI.ts +8 -0
- package/Server/API/ProbeAPI.ts +196 -15
- package/Server/API/ProjectAPI.ts +79 -1
- package/Server/API/ScheduledMaintenanceAPI.ts +33 -18
- package/Server/API/StatusPageAPI.ts +74 -37
- package/Server/API/WorkspaceNotificationRuleAPI.ts +34 -4
- package/Server/Infrastructure/Postgres/SchemaMigrations/1785241000000-AddColumnsToTableView.ts +13 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1785320000000-RepairCrossProjectIncidentReferences.ts +527 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1785329453269-AddParentGroupToStatusPageGroup.ts +31 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1785397674289-AddRecommendationDismissalTable.ts +55 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1785405581596-AddDroppedCountersToDropFilters.ts +53 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +10 -0
- package/Server/Services/AlertEpisodeService.ts +47 -0
- package/Server/Services/AlertService.ts +125 -0
- package/Server/Services/BillingService.ts +98 -0
- package/Server/Services/DatabaseService.ts +184 -20
- package/Server/Services/IncidentEpisodeService.ts +47 -0
- package/Server/Services/IncidentService.ts +123 -0
- package/Server/Services/IncidentTemplateService.ts +123 -1
- package/Server/Services/Index.ts +2 -0
- package/Server/Services/LogDropFilterService.ts +133 -0
- package/Server/Services/MonitorProbeService.ts +94 -4
- package/Server/Services/MonitorService.ts +48 -43
- package/Server/Services/NetworkDeviceDiscoveryScanService.ts +70 -0
- package/Server/Services/ProbeService.ts +66 -0
- package/Server/Services/ProjectService.ts +131 -7
- package/Server/Services/RecommendationDismissalService.ts +52 -0
- package/Server/Services/RunbookAgentJobService.ts +68 -7
- package/Server/Services/ScheduledMaintenanceService.ts +103 -0
- package/Server/Services/ScheduledMaintenanceTemplateService.ts +90 -0
- package/Server/Services/StatusPageGroupService.ts +186 -0
- package/Server/Services/TraceDropFilterService.ts +133 -0
- package/Server/Types/Workflow/Components/API/Delete.ts +12 -0
- package/Server/Types/Workflow/Components/API/Get.ts +12 -0
- package/Server/Types/Workflow/Components/API/Patch.ts +12 -0
- package/Server/Types/Workflow/Components/API/Post.ts +12 -0
- package/Server/Types/Workflow/Components/API/Put.ts +13 -0
- package/Server/Utils/Database/ProjectScopedReferenceValidator.ts +212 -0
- package/Server/Utils/DropFilterValidation.ts +127 -0
- package/Server/Utils/Errors.ts +5 -0
- package/Server/Utils/Monitor/MonitorAlert.ts +28 -1
- package/Server/Utils/Monitor/MonitorIncident.ts +31 -2
- package/Server/Utils/Telemetry/AppMetrics.ts +31 -0
- package/Tests/Models/AnalyticsModels/KubernetesCostAllocation.test.ts +16 -0
- package/Tests/Models/DatabaseModels/MonitorProbeColumnAccessControl.test.ts +196 -0
- package/Tests/Models/RecommendationDismissalModel.test.ts +269 -0
- package/Tests/Server/API/BaseAPIUpdatePayloadValidation.test.ts +320 -0
- package/Tests/Server/API/BaseAnalyticsAPIUpdatePayloadValidation.test.ts +293 -0
- package/Tests/Server/API/CommonAPIAuthGuard.test.ts +164 -0
- package/Tests/Server/API/ProbeAPI.test.ts +422 -53
- package/Tests/Server/API/ProjectAPI.test.ts +180 -0
- package/Tests/Server/API/ProjectAPIExtendTrialBillingDisabled.test.ts +138 -0
- package/Tests/Server/API/ProjectScopedCustomRouteAuth.test.ts +458 -0
- package/Tests/Server/Infrastructure/ContainerBootConfiguration.test.ts +359 -0
- package/Tests/Server/Infrastructure/ProcessSignalDelivery.test.ts +427 -0
- package/Tests/Server/Services/BillingServiceExtendTrial.test.ts +439 -0
- package/Tests/Server/Services/CrossProjectReferenceWriteGuard.test.ts +810 -0
- package/Tests/Server/Services/DatabaseServiceAtomicAddToColumns.test.ts +269 -0
- package/Tests/Server/Services/DatabaseServiceEmptyUpdate.test.ts +277 -0
- package/Tests/Server/Services/DatabaseServiceSortColumnSelect.test.ts +201 -0
- package/Tests/Server/Services/DiscoveryScanClaimHookFreeSafety.test.ts +81 -23
- package/Tests/Server/Services/DropFilterSaveValidation.test.ts +398 -0
- package/Tests/Server/Services/MonitorProbeDeleteHooks.test.ts +280 -0
- package/Tests/Server/Services/MonitorProbeServiceProbeTenancy.test.ts +304 -0
- package/Tests/Server/Services/NetworkDeviceDiscoveryScanService.test.ts +262 -0
- package/Tests/Server/Services/ProjectServiceExtendTrial.test.ts +614 -0
- package/Tests/Server/Services/RecommendationDismissalService.test.ts +306 -0
- package/Tests/Server/Services/RepairCrossProjectIncidentReferencesMigration.test.ts +528 -0
- package/Tests/Server/Services/StatusPageGroupNesting.test.ts +395 -0
- package/Tests/Server/TestingUtils/Services/BillingServiceHelper.ts +26 -21
- package/Tests/Server/Types/Database/Permissions/WorkflowVariableColumnPermission.test.ts +227 -0
- package/Tests/Server/Types/Workflow/Components/ApiComponentErrorPort.test.ts +285 -0
- package/Tests/Server/Utils/Database/ProjectScopedReferenceValidator.test.ts +463 -0
- package/Tests/Server/Utils/DropFilterValidation.test.ts +269 -0
- package/Tests/Server/Utils/Telemetry/SpanUtil.test.ts +94 -0
- package/Tests/Types/DateUserTimezone.test.ts +52 -0
- package/Tests/Types/JSONFunctions.test.ts +103 -1
- package/Tests/Types/Monitor/KubernetesAlertTemplates.test.ts +177 -9
- package/Tests/Types/Monitor/MonitorStepDnsMonitor.test.ts +105 -0
- package/Tests/Types/Monitor/MonitorStepDnssecMonitor.test.ts +131 -0
- package/Tests/Types/Monitor/MonitorStepDomainMonitor.test.ts +60 -0
- package/Tests/Types/Monitor/MonitorStepExternalStatusPageMonitor.test.ts +82 -0
- package/Tests/Types/Monitor/MonitorStepInfrastructureMonitors.test.ts +268 -0
- package/Tests/Types/Monitor/MonitorStepMetricMonitor.test.ts +386 -0
- package/Tests/Types/Monitor/MonitorStepProfileMonitor.test.ts +185 -0
- package/Tests/Types/Monitor/MonitorStepSnmpMonitor.test.ts +156 -0
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationCatalog.test.ts +371 -0
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationCoverage.test.ts +901 -0
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationNotificationMode.test.ts +607 -0
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.test.ts +754 -0
- package/Tests/Types/Monitor/Recommendation/MonitorRecommendationUtil.test.ts +960 -0
- package/Tests/Types/RollingTime/RollingTimeUtil.test.ts +186 -0
- package/Tests/Types/Runbook/RunbookStepTimeout.test.ts +410 -0
- package/Tests/Types/Telemetry/DropFilterSampling.test.ts +241 -0
- package/Tests/Types/Workspace/NotificationRuleConditionUtil.test.ts +353 -0
- package/Tests/Types/Workspace/NotificationRuleUtil.test.ts +566 -0
- package/Tests/UI/Components/CodeEditor.test.tsx +174 -0
- package/Tests/UI/Components/ErrorBoundary.test.tsx +555 -24
- package/Tests/UI/Components/InfoCard.test.tsx +358 -0
- package/Tests/UI/Components/LogTimeRangePicker.test.tsx +138 -0
- package/Tests/UI/Components/Modal.test.tsx +43 -5
- package/Tests/UI/Components/ModelTable/BaseModelTableColumnCustomization.test.tsx +679 -0
- package/Tests/UI/Components/ModelTable/BaseModelTableSearchLabels.test.tsx +397 -0
- package/Tests/UI/Components/ModelTable/ColumnCustomizationModal.test.tsx +999 -0
- package/Tests/UI/Components/ModelTable/ColumnPreference.test.ts +1678 -0
- package/Tests/UI/Components/ModelTable/CustomFieldColumns.test.tsx +1094 -0
- package/Tests/UI/Components/Runbook/StepTimeoutInput.test.tsx +386 -0
- package/Tests/UI/Components/StatusPage/ResourceGroupSection.test.tsx +671 -0
- package/Tests/UI/Components/TelemetryTimeRangePicker.test.tsx +404 -0
- package/Tests/UI/Utils/DropdownAlignment.test.ts +306 -0
- package/Tests/UI/Utils/TableFilterUrlState.test.ts +292 -0
- package/Tests/Utils/Monitor/MonitorSummaryProbeUtil.test.ts +263 -0
- package/Tests/Utils/NetworkDiscovery/ScanTargetUtil.test.ts +583 -0
- package/Tests/Utils/StatusPage/GroupNestingLayout.test.ts +1072 -0
- package/Tests/Utils/StatusPage/GroupTree.test.ts +583 -0
- package/Tests/Utils/StatusPage/ResourceUptime.test.ts +411 -0
- package/Tests/Utils/UserPreferences.test.ts +563 -0
- package/Types/Date.ts +15 -6
- package/Types/JSONFunctions.ts +7 -2
- package/Types/Kubernetes/KubernetesCostIngest.ts +37 -1
- package/Types/Monitor/KubernetesAlertTemplates.ts +205 -0
- package/Types/Monitor/MonitorStep.ts +10 -1
- package/Types/Monitor/MonitorStepMetricMonitor.ts +46 -1
- package/Types/Monitor/Recommendation/MonitorRecommendationCatalog.ts +413 -0
- package/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.ts +168 -0
- package/Types/Monitor/Recommendation/MonitorRecommendationTypes.ts +175 -0
- package/Types/Monitor/Recommendation/MonitorRecommendationUtil.ts +743 -0
- package/Types/Permission.ts +45 -0
- package/Types/Recommendation/RecommendationType.ts +20 -0
- package/Types/Runbook/RunbookExecutionDeadline.ts +129 -0
- package/Types/Runbook/RunbookStepTimeout.ts +202 -0
- package/Types/Telemetry/DropFilterSampling.ts +92 -0
- package/UI/Components/AI/GenerateFromAIModal.tsx +0 -2
- package/UI/Components/Accordion/Accordion.tsx +10 -2
- package/UI/Components/BulkUpdate/BulkLabelActions.tsx +0 -1
- package/UI/Components/CodeEditor/CodeEditor.tsx +34 -20
- package/UI/Components/Date/RangeStartAndEndDateView.tsx +0 -1
- package/UI/Components/EditionLabel/EditionLabel.tsx +1 -27
- package/UI/Components/Error/PageError.tsx +0 -4
- package/UI/Components/ErrorBoundary.tsx +252 -15
- package/UI/Components/InfoCard/InfoCard.tsx +58 -1
- package/UI/Components/LogsViewer/components/LogTimeRangePicker.tsx +34 -1
- package/UI/Components/MasterPage/MasterPage.tsx +65 -0
- package/UI/Components/Modal/Modal.tsx +16 -60
- package/UI/Components/ModelFormModal/ModelFormModal.tsx +0 -8
- package/UI/Components/ModelTable/BaseModelTable.tsx +503 -71
- package/UI/Components/ModelTable/Column.ts +17 -0
- package/UI/Components/ModelTable/ColumnCustomizationModal.tsx +523 -0
- package/UI/Components/ModelTable/ColumnPreference.ts +482 -0
- package/UI/Components/ModelTable/CustomFieldColumns.tsx +326 -0
- package/UI/Components/ModelTable/TableView.tsx +24 -2
- package/UI/Components/ModelTable/useCustomFieldColumns.ts +150 -0
- package/UI/Components/Runbook/StepTimeoutInput.tsx +173 -0
- package/UI/Components/SideMenu/SideMenu.tsx +24 -4
- package/UI/Components/StatusPage/ResourceGroupSection.tsx +231 -0
- package/UI/Components/Table/Table.tsx +14 -1
- package/UI/Components/Table/TableRow.tsx +180 -175
- package/UI/Components/Table/Types/Column.ts +2 -0
- package/UI/Components/TelemetryViewer/components/TelemetryTimeRangePicker.tsx +34 -1
- package/UI/Utils/DropdownAlignment.ts +162 -0
- package/UI/Utils/TableFilterUrlState.ts +59 -20
- package/Utils/API.ts +106 -2
- package/Utils/Monitor/MonitorSummaryProbeUtil.ts +130 -0
- package/Utils/NetworkDiscovery/ScanTargetUtil.ts +434 -0
- package/Utils/StatusPage/GroupNestingLayout.ts +343 -0
- package/Utils/StatusPage/GroupTree.ts +307 -0
- package/Utils/StatusPage/ResourceUptime.ts +90 -17
- package/Utils/UserPreferences.ts +53 -0
- package/build/dist/Models/AnalyticsModels/KubernetesCostAllocation.js +86 -0
- package/build/dist/Models/AnalyticsModels/KubernetesCostAllocation.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AlertEpisodeStateTimeline.js +1 -0
- package/build/dist/Models/DatabaseModels/AlertEpisodeStateTimeline.js.map +1 -1
- package/build/dist/Models/DatabaseModels/AlertStateTimeline.js +1 -0
- package/build/dist/Models/DatabaseModels/AlertStateTimeline.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentEpisodeStateTimeline.js +1 -0
- package/build/dist/Models/DatabaseModels/IncidentEpisodeStateTimeline.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentStateTimeline.js +1 -0
- package/build/dist/Models/DatabaseModels/IncidentStateTimeline.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Index.js +2 -0
- package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/LogDropFilter.js +91 -0
- package/build/dist/Models/DatabaseModels/LogDropFilter.js.map +1 -1
- package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js +14 -4
- package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js.map +1 -1
- package/build/dist/Models/DatabaseModels/RecommendationDismissal.js +484 -0
- package/build/dist/Models/DatabaseModels/RecommendationDismissal.js.map +1 -0
- package/build/dist/Models/DatabaseModels/ScheduledMaintenanceStateTimeline.js +1 -0
- package/build/dist/Models/DatabaseModels/ScheduledMaintenanceStateTimeline.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPageGroup.js +94 -0
- package/build/dist/Models/DatabaseModels/StatusPageGroup.js.map +1 -1
- package/build/dist/Models/DatabaseModels/TableView.js +40 -0
- package/build/dist/Models/DatabaseModels/TableView.js.map +1 -1
- package/build/dist/Models/DatabaseModels/TraceDropFilter.js +91 -0
- package/build/dist/Models/DatabaseModels/TraceDropFilter.js.map +1 -1
- package/build/dist/Models/DatabaseModels/WorkflowVariable.js +5 -1
- package/build/dist/Models/DatabaseModels/WorkflowVariable.js.map +1 -1
- package/build/dist/Server/API/AlertAPI.js +22 -13
- package/build/dist/Server/API/AlertAPI.js.map +1 -1
- package/build/dist/Server/API/BaseAPI.js +22 -1
- package/build/dist/Server/API/BaseAPI.js.map +1 -1
- package/build/dist/Server/API/BaseAnalyticsAPI.js +24 -1
- package/build/dist/Server/API/BaseAnalyticsAPI.js.map +1 -1
- package/build/dist/Server/API/CommonAPI.js +42 -0
- package/build/dist/Server/API/CommonAPI.js.map +1 -1
- package/build/dist/Server/API/IncidentAPI.js +43 -26
- package/build/dist/Server/API/IncidentAPI.js.map +1 -1
- package/build/dist/Server/API/IncidentEpisodeAPI.js +21 -12
- package/build/dist/Server/API/IncidentEpisodeAPI.js.map +1 -1
- package/build/dist/Server/API/MonitorAPI.js +23 -0
- package/build/dist/Server/API/MonitorAPI.js.map +1 -1
- package/build/dist/Server/API/MonitorTemplateAPI.js +4 -0
- package/build/dist/Server/API/MonitorTemplateAPI.js.map +1 -1
- package/build/dist/Server/API/ProbeAPI.js +131 -15
- package/build/dist/Server/API/ProbeAPI.js.map +1 -1
- package/build/dist/Server/API/ProjectAPI.js +62 -3
- package/build/dist/Server/API/ProjectAPI.js.map +1 -1
- package/build/dist/Server/API/ScheduledMaintenanceAPI.js +23 -14
- package/build/dist/Server/API/ScheduledMaintenanceAPI.js.map +1 -1
- package/build/dist/Server/API/StatusPageAPI.js +61 -33
- package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
- package/build/dist/Server/API/WorkspaceNotificationRuleAPI.js +26 -2
- package/build/dist/Server/API/WorkspaceNotificationRuleAPI.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785241000000-AddColumnsToTableView.js +12 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785241000000-AddColumnsToTableView.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785320000000-RepairCrossProjectIncidentReferences.js +397 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785320000000-RepairCrossProjectIncidentReferences.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785329453269-AddParentGroupToStatusPageGroup.js +16 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785329453269-AddParentGroupToStatusPageGroup.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785397674289-AddRecommendationDismissalTable.js +30 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785397674289-AddRecommendationDismissalTable.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785405581596-AddDroppedCountersToDropFilters.js +34 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785405581596-AddDroppedCountersToDropFilters.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +10 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Services/AlertEpisodeService.js +39 -0
- package/build/dist/Server/Services/AlertEpisodeService.js.map +1 -1
- package/build/dist/Server/Services/AlertService.js +95 -0
- package/build/dist/Server/Services/AlertService.js.map +1 -1
- package/build/dist/Server/Services/BillingService.js +71 -0
- package/build/dist/Server/Services/BillingService.js.map +1 -1
- package/build/dist/Server/Services/DatabaseService.js +140 -17
- package/build/dist/Server/Services/DatabaseService.js.map +1 -1
- package/build/dist/Server/Services/IncidentEpisodeService.js +39 -0
- package/build/dist/Server/Services/IncidentEpisodeService.js.map +1 -1
- package/build/dist/Server/Services/IncidentService.js +100 -0
- package/build/dist/Server/Services/IncidentService.js.map +1 -1
- package/build/dist/Server/Services/IncidentTemplateService.js +97 -0
- package/build/dist/Server/Services/IncidentTemplateService.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/LogDropFilterService.js +93 -0
- package/build/dist/Server/Services/LogDropFilterService.js.map +1 -1
- package/build/dist/Server/Services/MonitorProbeService.js +73 -5
- package/build/dist/Server/Services/MonitorProbeService.js.map +1 -1
- package/build/dist/Server/Services/MonitorService.js +34 -39
- package/build/dist/Server/Services/MonitorService.js.map +1 -1
- package/build/dist/Server/Services/NetworkDeviceDiscoveryScanService.js +71 -0
- package/build/dist/Server/Services/NetworkDeviceDiscoveryScanService.js.map +1 -1
- package/build/dist/Server/Services/ProbeService.js +64 -0
- package/build/dist/Server/Services/ProbeService.js.map +1 -1
- package/build/dist/Server/Services/ProjectService.js +103 -7
- package/build/dist/Server/Services/ProjectService.js.map +1 -1
- package/build/dist/Server/Services/RecommendationDismissalService.js +50 -0
- package/build/dist/Server/Services/RecommendationDismissalService.js.map +1 -0
- package/build/dist/Server/Services/RunbookAgentJobService.js +63 -5
- package/build/dist/Server/Services/RunbookAgentJobService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenanceService.js +83 -0
- package/build/dist/Server/Services/ScheduledMaintenanceService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenanceTemplateService.js +65 -0
- package/build/dist/Server/Services/ScheduledMaintenanceTemplateService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageGroupService.js +136 -0
- package/build/dist/Server/Services/StatusPageGroupService.js.map +1 -1
- package/build/dist/Server/Services/TraceDropFilterService.js +93 -0
- package/build/dist/Server/Services/TraceDropFilterService.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Delete.js +11 -0
- package/build/dist/Server/Types/Workflow/Components/API/Delete.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Get.js +11 -0
- package/build/dist/Server/Types/Workflow/Components/API/Get.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Patch.js +11 -0
- package/build/dist/Server/Types/Workflow/Components/API/Patch.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Post.js +11 -0
- package/build/dist/Server/Types/Workflow/Components/API/Post.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/API/Put.js +12 -0
- package/build/dist/Server/Types/Workflow/Components/API/Put.js.map +1 -1
- package/build/dist/Server/Utils/Database/ProjectScopedReferenceValidator.js +132 -0
- package/build/dist/Server/Utils/Database/ProjectScopedReferenceValidator.js.map +1 -0
- package/build/dist/Server/Utils/DropFilterValidation.js +80 -0
- package/build/dist/Server/Utils/DropFilterValidation.js.map +1 -0
- package/build/dist/Server/Utils/Errors.js +3 -0
- package/build/dist/Server/Utils/Errors.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorAlert.js +30 -12
- package/build/dist/Server/Utils/Monitor/MonitorAlert.js.map +1 -1
- package/build/dist/Server/Utils/Monitor/MonitorIncident.js +38 -18
- package/build/dist/Server/Utils/Monitor/MonitorIncident.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/AppMetrics.js +26 -0
- package/build/dist/Server/Utils/Telemetry/AppMetrics.js.map +1 -1
- package/build/dist/Types/Date.js +14 -4
- package/build/dist/Types/Date.js.map +1 -1
- package/build/dist/Types/JSONFunctions.js +8 -3
- package/build/dist/Types/JSONFunctions.js.map +1 -1
- package/build/dist/Types/Kubernetes/KubernetesCostIngest.js.map +1 -1
- package/build/dist/Types/Monitor/KubernetesAlertTemplates.js +192 -0
- package/build/dist/Types/Monitor/KubernetesAlertTemplates.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStep.js +6 -1
- package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
- package/build/dist/Types/Monitor/MonitorStepMetricMonitor.js +32 -1
- package/build/dist/Types/Monitor/MonitorStepMetricMonitor.js.map +1 -1
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js +294 -0
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js.map +1 -0
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.js +110 -0
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.js.map +1 -0
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js +58 -0
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js.map +1 -0
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationUtil.js +451 -0
- package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationUtil.js.map +1 -0
- package/build/dist/Types/Permission.js +40 -0
- package/build/dist/Types/Permission.js.map +1 -1
- package/build/dist/Types/Recommendation/RecommendationType.js +21 -0
- package/build/dist/Types/Recommendation/RecommendationType.js.map +1 -0
- package/build/dist/Types/Runbook/RunbookExecutionDeadline.js +93 -0
- package/build/dist/Types/Runbook/RunbookExecutionDeadline.js.map +1 -0
- package/build/dist/Types/Runbook/RunbookStepTimeout.js +142 -0
- package/build/dist/Types/Runbook/RunbookStepTimeout.js.map +1 -0
- package/build/dist/Types/Telemetry/DropFilterSampling.js +75 -0
- package/build/dist/Types/Telemetry/DropFilterSampling.js.map +1 -0
- package/build/dist/UI/Components/AI/GenerateFromAIModal.js +1 -2
- package/build/dist/UI/Components/AI/GenerateFromAIModal.js.map +1 -1
- package/build/dist/UI/Components/Accordion/Accordion.js +9 -2
- package/build/dist/UI/Components/Accordion/Accordion.js.map +1 -1
- package/build/dist/UI/Components/BulkUpdate/BulkLabelActions.js +1 -1
- package/build/dist/UI/Components/BulkUpdate/BulkLabelActions.js.map +1 -1
- package/build/dist/UI/Components/CodeEditor/CodeEditor.js +27 -14
- package/build/dist/UI/Components/CodeEditor/CodeEditor.js.map +1 -1
- package/build/dist/UI/Components/Date/RangeStartAndEndDateView.js +1 -1
- package/build/dist/UI/Components/Date/RangeStartAndEndDateView.js.map +1 -1
- package/build/dist/UI/Components/EditionLabel/EditionLabel.js +2 -20
- package/build/dist/UI/Components/EditionLabel/EditionLabel.js.map +1 -1
- package/build/dist/UI/Components/Error/PageError.js +1 -3
- package/build/dist/UI/Components/Error/PageError.js.map +1 -1
- package/build/dist/UI/Components/ErrorBoundary.js +145 -11
- package/build/dist/UI/Components/ErrorBoundary.js.map +1 -1
- package/build/dist/UI/Components/InfoCard/InfoCard.js +28 -1
- package/build/dist/UI/Components/InfoCard/InfoCard.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogTimeRangePicker.js +13 -2
- package/build/dist/UI/Components/LogsViewer/components/LogTimeRangePicker.js.map +1 -1
- package/build/dist/UI/Components/MasterPage/MasterPage.js +50 -1
- package/build/dist/UI/Components/MasterPage/MasterPage.js.map +1 -1
- package/build/dist/UI/Components/Modal/Modal.js +4 -32
- package/build/dist/UI/Components/Modal/Modal.js.map +1 -1
- package/build/dist/UI/Components/ModelFormModal/ModelFormModal.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js +308 -40
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/ColumnCustomizationModal.js +230 -0
- package/build/dist/UI/Components/ModelTable/ColumnCustomizationModal.js.map +1 -0
- package/build/dist/UI/Components/ModelTable/ColumnPreference.js +258 -0
- package/build/dist/UI/Components/ModelTable/ColumnPreference.js.map +1 -0
- package/build/dist/UI/Components/ModelTable/CustomFieldColumns.js +168 -0
- package/build/dist/UI/Components/ModelTable/CustomFieldColumns.js.map +1 -0
- package/build/dist/UI/Components/ModelTable/TableView.js +13 -2
- package/build/dist/UI/Components/ModelTable/TableView.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/useCustomFieldColumns.js +84 -0
- package/build/dist/UI/Components/ModelTable/useCustomFieldColumns.js.map +1 -0
- package/build/dist/UI/Components/Runbook/StepTimeoutInput.js +101 -0
- package/build/dist/UI/Components/Runbook/StepTimeoutInput.js.map +1 -0
- package/build/dist/UI/Components/SideMenu/SideMenu.js +15 -5
- package/build/dist/UI/Components/SideMenu/SideMenu.js.map +1 -1
- package/build/dist/UI/Components/StatusPage/ResourceGroupSection.js +73 -0
- package/build/dist/UI/Components/StatusPage/ResourceGroupSection.js.map +1 -0
- package/build/dist/UI/Components/Table/Table.js +15 -2
- package/build/dist/UI/Components/Table/Table.js.map +1 -1
- package/build/dist/UI/Components/Table/TableRow.js +11 -6
- package/build/dist/UI/Components/Table/TableRow.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryTimeRangePicker.js +13 -2
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryTimeRangePicker.js.map +1 -1
- package/build/dist/UI/Utils/DropdownAlignment.js +98 -0
- package/build/dist/UI/Utils/DropdownAlignment.js.map +1 -0
- package/build/dist/UI/Utils/TableFilterUrlState.js +48 -15
- package/build/dist/UI/Utils/TableFilterUrlState.js.map +1 -1
- package/build/dist/Utils/API.js +39 -2
- package/build/dist/Utils/API.js.map +1 -1
- package/build/dist/Utils/Monitor/MonitorSummaryProbeUtil.js +97 -0
- package/build/dist/Utils/Monitor/MonitorSummaryProbeUtil.js.map +1 -0
- package/build/dist/Utils/NetworkDiscovery/ScanTargetUtil.js +330 -0
- package/build/dist/Utils/NetworkDiscovery/ScanTargetUtil.js.map +1 -0
- package/build/dist/Utils/StatusPage/GroupNestingLayout.js +280 -0
- package/build/dist/Utils/StatusPage/GroupNestingLayout.js.map +1 -0
- package/build/dist/Utils/StatusPage/GroupTree.js +214 -0
- package/build/dist/Utils/StatusPage/GroupTree.js.map +1 -0
- package/build/dist/Utils/StatusPage/ResourceUptime.js +60 -16
- package/build/dist/Utils/StatusPage/ResourceUptime.js.map +1 -1
- package/build/dist/Utils/UserPreferences.js +33 -0
- package/build/dist/Utils/UserPreferences.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,810 @@
|
|
|
1
|
+
import AlertEpisodeService from "../../../Server/Services/AlertEpisodeService";
|
|
2
|
+
import AlertService from "../../../Server/Services/AlertService";
|
|
3
|
+
import AlertSeverityService from "../../../Server/Services/AlertSeverityService";
|
|
4
|
+
import AlertStateService from "../../../Server/Services/AlertStateService";
|
|
5
|
+
import IncidentEpisodeService from "../../../Server/Services/IncidentEpisodeService";
|
|
6
|
+
import IncidentService from "../../../Server/Services/IncidentService";
|
|
7
|
+
import IncidentSeverityService from "../../../Server/Services/IncidentSeverityService";
|
|
8
|
+
import IncidentStateService from "../../../Server/Services/IncidentStateService";
|
|
9
|
+
import IncidentTemplateService from "../../../Server/Services/IncidentTemplateService";
|
|
10
|
+
import MonitorService from "../../../Server/Services/MonitorService";
|
|
11
|
+
import MonitorStatusService from "../../../Server/Services/MonitorStatusService";
|
|
12
|
+
import ProjectService from "../../../Server/Services/ProjectService";
|
|
13
|
+
import ScheduledMaintenanceService from "../../../Server/Services/ScheduledMaintenanceService";
|
|
14
|
+
import ScheduledMaintenanceStateService from "../../../Server/Services/ScheduledMaintenanceStateService";
|
|
15
|
+
import ScheduledMaintenanceTemplateService from "../../../Server/Services/ScheduledMaintenanceTemplateService";
|
|
16
|
+
import DatabaseService from "../../../Server/Services/DatabaseService";
|
|
17
|
+
import ProjectScopedReferenceValidator from "../../../Server/Utils/Database/ProjectScopedReferenceValidator";
|
|
18
|
+
import DatabaseBaseModel from "../../../Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel";
|
|
19
|
+
import Alert from "../../../Models/DatabaseModels/Alert";
|
|
20
|
+
import AlertEpisode from "../../../Models/DatabaseModels/AlertEpisode";
|
|
21
|
+
import AlertState from "../../../Models/DatabaseModels/AlertState";
|
|
22
|
+
import Incident from "../../../Models/DatabaseModels/Incident";
|
|
23
|
+
import IncidentEpisode from "../../../Models/DatabaseModels/IncidentEpisode";
|
|
24
|
+
import IncidentState from "../../../Models/DatabaseModels/IncidentState";
|
|
25
|
+
import IncidentTemplate from "../../../Models/DatabaseModels/IncidentTemplate";
|
|
26
|
+
import ScheduledMaintenance from "../../../Models/DatabaseModels/ScheduledMaintenance";
|
|
27
|
+
import ScheduledMaintenanceState from "../../../Models/DatabaseModels/ScheduledMaintenanceState";
|
|
28
|
+
import ScheduledMaintenanceTemplate from "../../../Models/DatabaseModels/ScheduledMaintenanceTemplate";
|
|
29
|
+
import BadDataException from "../../../Types/Exception/BadDataException";
|
|
30
|
+
import ObjectID from "../../../Types/ObjectID";
|
|
31
|
+
import {
|
|
32
|
+
afterEach,
|
|
33
|
+
beforeEach,
|
|
34
|
+
describe,
|
|
35
|
+
expect,
|
|
36
|
+
jest,
|
|
37
|
+
test,
|
|
38
|
+
} from "@jest/globals";
|
|
39
|
+
|
|
40
|
+
/*
|
|
41
|
+
* The undeletable project came from writes, not from deletes: a record was
|
|
42
|
+
* saved holding another project's state / severity / monitor status id, and
|
|
43
|
+
* the ON DELETE NO ACTION foreign key then refused to let that other project
|
|
44
|
+
* go. The repair migration cleans up the rows that already exist; these tests
|
|
45
|
+
* cover the other half — the write paths that produced them must now refuse.
|
|
46
|
+
*
|
|
47
|
+
* Each captured reference is asserted as the full triple (model name, id,
|
|
48
|
+
* lookup service). The service is the part that picks the table the id is
|
|
49
|
+
* checked against, so a test that ignores it passes even when a column is
|
|
50
|
+
* validated against the wrong model — which is exactly what a mutation run
|
|
51
|
+
* showed the first version of this file doing.
|
|
52
|
+
*/
|
|
53
|
+
|
|
54
|
+
const PROJECT_ID: ObjectID = new ObjectID(
|
|
55
|
+
"0b5fbbd0-8d1c-4a72-9a2b-4b8bd1cba0e9",
|
|
56
|
+
);
|
|
57
|
+
const STATE_ID: ObjectID = new ObjectID("2b0a94a4-2f8c-49f0-8a2e-0f1ff5df41c9");
|
|
58
|
+
const SEVERITY_ID: ObjectID = new ObjectID(
|
|
59
|
+
"6a56b0f9-6c8f-4f76-9b53-0a1a5b0ec1a2",
|
|
60
|
+
);
|
|
61
|
+
const MONITOR_STATUS_ID: ObjectID = new ObjectID(
|
|
62
|
+
"8ff02a3f-3f18-4c1d-9db1-6cf27bb2a4a1",
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
// Identity -> readable name, so an assertion can name the service it expects.
|
|
66
|
+
const SERVICE_NAMES: Map<unknown, string> = new Map<unknown, string>([
|
|
67
|
+
[IncidentStateService, "IncidentStateService"],
|
|
68
|
+
[IncidentSeverityService, "IncidentSeverityService"],
|
|
69
|
+
[AlertStateService, "AlertStateService"],
|
|
70
|
+
[AlertSeverityService, "AlertSeverityService"],
|
|
71
|
+
[ScheduledMaintenanceStateService, "ScheduledMaintenanceStateService"],
|
|
72
|
+
[MonitorStatusService, "MonitorStatusService"],
|
|
73
|
+
]);
|
|
74
|
+
|
|
75
|
+
type CapturedReference = {
|
|
76
|
+
subject: string;
|
|
77
|
+
modelName: string;
|
|
78
|
+
id: string;
|
|
79
|
+
service: string;
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
type ValidatorCall = {
|
|
83
|
+
projectId: ObjectID | undefined;
|
|
84
|
+
subject?: string | undefined;
|
|
85
|
+
references: Array<{
|
|
86
|
+
modelName: string;
|
|
87
|
+
id: ObjectID | string | undefined | null;
|
|
88
|
+
service: DatabaseService<DatabaseBaseModel>;
|
|
89
|
+
}>;
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
let captured: Array<CapturedReference> = [];
|
|
93
|
+
let validatorCalls: Array<ValidatorCall> = [];
|
|
94
|
+
|
|
95
|
+
/*
|
|
96
|
+
* Records every (subject, model, id, service) the production code asks about,
|
|
97
|
+
* and optionally rejects. `rejects` throws only when the call carries at least
|
|
98
|
+
* one id, so a guard that has been emptied out cannot masquerade as a working
|
|
99
|
+
* one by throwing anyway.
|
|
100
|
+
*/
|
|
101
|
+
function spyOnValidator(rejects?: boolean): void {
|
|
102
|
+
jest
|
|
103
|
+
.spyOn(ProjectScopedReferenceValidator, "validateReferencesBelongToProject")
|
|
104
|
+
.mockImplementation((async (data: ValidatorCall): Promise<void> => {
|
|
105
|
+
validatorCalls.push(data);
|
|
106
|
+
|
|
107
|
+
let hasId: boolean = false;
|
|
108
|
+
|
|
109
|
+
for (const reference of data.references) {
|
|
110
|
+
if (!reference.id) {
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
hasId = true;
|
|
115
|
+
|
|
116
|
+
captured.push({
|
|
117
|
+
subject: data.subject || "",
|
|
118
|
+
modelName: reference.modelName,
|
|
119
|
+
id: reference.id.toString(),
|
|
120
|
+
service: SERVICE_NAMES.get(reference.service) || "UNKNOWN_SERVICE",
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (rejects && hasId) {
|
|
125
|
+
throw new BadDataException(
|
|
126
|
+
"This record references records that belong to a different project.",
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
}) as never);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function callHook(
|
|
133
|
+
service: unknown,
|
|
134
|
+
hook: "onBeforeCreate" | "onBeforeUpdate",
|
|
135
|
+
payload: unknown,
|
|
136
|
+
): Promise<unknown> {
|
|
137
|
+
return (service as Record<string, (input: unknown) => Promise<unknown>>)[
|
|
138
|
+
hook
|
|
139
|
+
]!(payload);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
describe("cross-project reference guard on write", () => {
|
|
143
|
+
beforeEach(() => {
|
|
144
|
+
captured = [];
|
|
145
|
+
validatorCalls = [];
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
afterEach(() => {
|
|
149
|
+
jest.restoreAllMocks();
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
describe("IncidentService", () => {
|
|
153
|
+
function mockCreatedState(): void {
|
|
154
|
+
const createdState: IncidentState = new IncidentState();
|
|
155
|
+
createdState._id = STATE_ID.toString();
|
|
156
|
+
jest
|
|
157
|
+
.spyOn(IncidentStateService, "findOneBy")
|
|
158
|
+
.mockResolvedValue(createdState as never);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
test("create checks state, severity and monitor status against the right models", async () => {
|
|
162
|
+
mockCreatedState();
|
|
163
|
+
spyOnValidator();
|
|
164
|
+
jest
|
|
165
|
+
.spyOn(ProjectService, "incrementAndGetIncidentCounter")
|
|
166
|
+
.mockResolvedValue({ counter: 1, prefix: undefined } as never);
|
|
167
|
+
|
|
168
|
+
await callHook(IncidentService, "onBeforeCreate", {
|
|
169
|
+
data: {
|
|
170
|
+
title: "test",
|
|
171
|
+
incidentSeverityId: SEVERITY_ID,
|
|
172
|
+
changeMonitorStatusToId: MONITOR_STATUS_ID,
|
|
173
|
+
} as Incident,
|
|
174
|
+
props: { tenantId: PROJECT_ID },
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
expect(captured).toEqual([
|
|
178
|
+
{
|
|
179
|
+
subject: "incident",
|
|
180
|
+
modelName: "Incident State",
|
|
181
|
+
id: STATE_ID.toString(),
|
|
182
|
+
service: "IncidentStateService",
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
subject: "incident",
|
|
186
|
+
modelName: "Incident Severity",
|
|
187
|
+
id: SEVERITY_ID.toString(),
|
|
188
|
+
service: "IncidentSeverityService",
|
|
189
|
+
},
|
|
190
|
+
{
|
|
191
|
+
subject: "incident",
|
|
192
|
+
modelName: "Monitor Status",
|
|
193
|
+
id: MONITOR_STATUS_ID.toString(),
|
|
194
|
+
service: "MonitorStatusService",
|
|
195
|
+
},
|
|
196
|
+
]);
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
test("create is rejected, and burns no incident number, when a reference is foreign", async () => {
|
|
200
|
+
mockCreatedState();
|
|
201
|
+
spyOnValidator(true);
|
|
202
|
+
const counter: jest.Mock = jest.fn() as unknown as jest.Mock;
|
|
203
|
+
jest
|
|
204
|
+
.spyOn(ProjectService, "incrementAndGetIncidentCounter")
|
|
205
|
+
.mockImplementation(counter as never);
|
|
206
|
+
|
|
207
|
+
await expect(
|
|
208
|
+
callHook(IncidentService, "onBeforeCreate", {
|
|
209
|
+
data: { title: "test", incidentSeverityId: SEVERITY_ID } as Incident,
|
|
210
|
+
props: { tenantId: PROJECT_ID },
|
|
211
|
+
}),
|
|
212
|
+
).rejects.toThrow("belong to a different project");
|
|
213
|
+
|
|
214
|
+
expect(counter).not.toHaveBeenCalled();
|
|
215
|
+
});
|
|
216
|
+
|
|
217
|
+
test("update checks every reference column it writes", async () => {
|
|
218
|
+
spyOnValidator();
|
|
219
|
+
|
|
220
|
+
/*
|
|
221
|
+
* Writing changeMonitorStatusToId also sends onBeforeUpdate into its
|
|
222
|
+
* monitor-status-propagation branch, which reads the matched incidents
|
|
223
|
+
* with the caller's own props. Unrelated to the guard — stub it out.
|
|
224
|
+
*/
|
|
225
|
+
jest.spyOn(IncidentService, "findBy").mockResolvedValue([] as never);
|
|
226
|
+
|
|
227
|
+
await callHook(IncidentService, "onBeforeUpdate", {
|
|
228
|
+
data: {
|
|
229
|
+
currentIncidentStateId: STATE_ID,
|
|
230
|
+
incidentSeverityId: SEVERITY_ID,
|
|
231
|
+
changeMonitorStatusToId: MONITOR_STATUS_ID,
|
|
232
|
+
},
|
|
233
|
+
query: {},
|
|
234
|
+
props: { tenantId: PROJECT_ID },
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
expect(captured).toEqual([
|
|
238
|
+
{
|
|
239
|
+
subject: "incident",
|
|
240
|
+
modelName: "Incident State",
|
|
241
|
+
id: STATE_ID.toString(),
|
|
242
|
+
service: "IncidentStateService",
|
|
243
|
+
},
|
|
244
|
+
{
|
|
245
|
+
subject: "incident",
|
|
246
|
+
modelName: "Incident Severity",
|
|
247
|
+
id: SEVERITY_ID.toString(),
|
|
248
|
+
service: "IncidentSeverityService",
|
|
249
|
+
},
|
|
250
|
+
{
|
|
251
|
+
subject: "incident",
|
|
252
|
+
modelName: "Monitor Status",
|
|
253
|
+
id: MONITOR_STATUS_ID.toString(),
|
|
254
|
+
service: "MonitorStatusService",
|
|
255
|
+
},
|
|
256
|
+
]);
|
|
257
|
+
});
|
|
258
|
+
|
|
259
|
+
test("update catches the bare-string relation shape the API accepts", async () => {
|
|
260
|
+
/*
|
|
261
|
+
* PUT /api/incident with {"incidentSeverity": "<uuid>"} leaves a plain
|
|
262
|
+
* string in the relation slot until sanitizeCreateOrUpdate turns it into
|
|
263
|
+
* an entity — which happens after this hook. Reading ?._id alone missed
|
|
264
|
+
* it and the guard silently passed.
|
|
265
|
+
*/
|
|
266
|
+
spyOnValidator();
|
|
267
|
+
|
|
268
|
+
await callHook(IncidentService, "onBeforeUpdate", {
|
|
269
|
+
data: { incidentSeverity: SEVERITY_ID.toString() },
|
|
270
|
+
query: {},
|
|
271
|
+
props: { tenantId: PROJECT_ID },
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
expect(captured).toEqual([
|
|
275
|
+
{
|
|
276
|
+
subject: "incident",
|
|
277
|
+
modelName: "Incident Severity",
|
|
278
|
+
id: SEVERITY_ID.toString(),
|
|
279
|
+
service: "IncidentSeverityService",
|
|
280
|
+
},
|
|
281
|
+
]);
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
test("update catches the relation-object shape", async () => {
|
|
285
|
+
spyOnValidator();
|
|
286
|
+
|
|
287
|
+
await callHook(IncidentService, "onBeforeUpdate", {
|
|
288
|
+
data: { incidentSeverity: { _id: SEVERITY_ID.toString() } },
|
|
289
|
+
query: {},
|
|
290
|
+
props: { tenantId: PROJECT_ID },
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
expect(captured).toHaveLength(1);
|
|
294
|
+
expect(captured[0]?.id).toBe(SEVERITY_ID.toString());
|
|
295
|
+
});
|
|
296
|
+
|
|
297
|
+
test("update looks nothing up when no reference column is written", async () => {
|
|
298
|
+
spyOnValidator();
|
|
299
|
+
|
|
300
|
+
await callHook(IncidentService, "onBeforeUpdate", {
|
|
301
|
+
data: { title: "renamed" },
|
|
302
|
+
query: {},
|
|
303
|
+
props: { tenantId: PROJECT_ID },
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
expect(validatorCalls).toHaveLength(0);
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
test("update falls back to the projects of the matched rows when there is no tenant", async () => {
|
|
310
|
+
/*
|
|
311
|
+
* Root and API updates do not always carry a tenantId. Skipping the
|
|
312
|
+
* check there would leave the exact hole this guard exists to close.
|
|
313
|
+
*/
|
|
314
|
+
const incident: Incident = new Incident();
|
|
315
|
+
incident.projectId = PROJECT_ID;
|
|
316
|
+
|
|
317
|
+
jest
|
|
318
|
+
.spyOn(IncidentService, "findBy")
|
|
319
|
+
.mockResolvedValue([incident] as never);
|
|
320
|
+
|
|
321
|
+
spyOnValidator();
|
|
322
|
+
|
|
323
|
+
await callHook(IncidentService, "onBeforeUpdate", {
|
|
324
|
+
data: { incidentSeverityId: SEVERITY_ID },
|
|
325
|
+
query: {},
|
|
326
|
+
props: { isRoot: true },
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
expect(validatorCalls).toHaveLength(1);
|
|
330
|
+
expect(validatorCalls[0]?.projectId).toBe(PROJECT_ID);
|
|
331
|
+
});
|
|
332
|
+
|
|
333
|
+
test("update is rejected when a reference is foreign", async () => {
|
|
334
|
+
spyOnValidator(true);
|
|
335
|
+
|
|
336
|
+
await expect(
|
|
337
|
+
callHook(IncidentService, "onBeforeUpdate", {
|
|
338
|
+
data: { incidentSeverityId: SEVERITY_ID },
|
|
339
|
+
query: {},
|
|
340
|
+
props: { tenantId: PROJECT_ID },
|
|
341
|
+
}),
|
|
342
|
+
).rejects.toThrow("belong to a different project");
|
|
343
|
+
});
|
|
344
|
+
});
|
|
345
|
+
|
|
346
|
+
describe("AlertService", () => {
|
|
347
|
+
function mockCreatedState(): void {
|
|
348
|
+
const createdState: AlertState = new AlertState();
|
|
349
|
+
createdState._id = STATE_ID.toString();
|
|
350
|
+
jest
|
|
351
|
+
.spyOn(AlertStateService, "findOneBy")
|
|
352
|
+
.mockResolvedValue(createdState as never);
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
test("create checks severity and monitor status against the right models", async () => {
|
|
356
|
+
mockCreatedState();
|
|
357
|
+
spyOnValidator();
|
|
358
|
+
jest
|
|
359
|
+
.spyOn(ProjectService, "incrementAndGetAlertCounter")
|
|
360
|
+
.mockResolvedValue({ counter: 1, prefix: undefined } as never);
|
|
361
|
+
|
|
362
|
+
await callHook(AlertService, "onBeforeCreate", {
|
|
363
|
+
data: {
|
|
364
|
+
title: "test",
|
|
365
|
+
alertSeverityId: SEVERITY_ID,
|
|
366
|
+
monitorStatusWhenThisAlertWasCreatedId: MONITOR_STATUS_ID,
|
|
367
|
+
} as Alert,
|
|
368
|
+
props: { tenantId: PROJECT_ID },
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
expect(captured).toEqual([
|
|
372
|
+
{
|
|
373
|
+
subject: "alert",
|
|
374
|
+
modelName: "Alert Severity",
|
|
375
|
+
id: SEVERITY_ID.toString(),
|
|
376
|
+
service: "AlertSeverityService",
|
|
377
|
+
},
|
|
378
|
+
{
|
|
379
|
+
subject: "alert",
|
|
380
|
+
modelName: "Monitor Status",
|
|
381
|
+
id: MONITOR_STATUS_ID.toString(),
|
|
382
|
+
service: "MonitorStatusService",
|
|
383
|
+
},
|
|
384
|
+
]);
|
|
385
|
+
});
|
|
386
|
+
|
|
387
|
+
test("create is rejected, and burns no alert number, when a reference is foreign", async () => {
|
|
388
|
+
mockCreatedState();
|
|
389
|
+
spyOnValidator(true);
|
|
390
|
+
const counter: jest.Mock = jest.fn() as unknown as jest.Mock;
|
|
391
|
+
jest
|
|
392
|
+
.spyOn(ProjectService, "incrementAndGetAlertCounter")
|
|
393
|
+
.mockImplementation(counter as never);
|
|
394
|
+
|
|
395
|
+
await expect(
|
|
396
|
+
callHook(AlertService, "onBeforeCreate", {
|
|
397
|
+
data: { title: "test", alertSeverityId: SEVERITY_ID } as Alert,
|
|
398
|
+
props: { tenantId: PROJECT_ID },
|
|
399
|
+
}),
|
|
400
|
+
).rejects.toThrow("belong to a different project");
|
|
401
|
+
|
|
402
|
+
expect(counter).not.toHaveBeenCalled();
|
|
403
|
+
});
|
|
404
|
+
|
|
405
|
+
test("update checks state, severity and monitor status", async () => {
|
|
406
|
+
spyOnValidator();
|
|
407
|
+
|
|
408
|
+
await callHook(AlertService, "onBeforeUpdate", {
|
|
409
|
+
data: {
|
|
410
|
+
currentAlertStateId: STATE_ID,
|
|
411
|
+
alertSeverityId: SEVERITY_ID,
|
|
412
|
+
monitorStatusWhenThisAlertWasCreatedId: MONITOR_STATUS_ID,
|
|
413
|
+
},
|
|
414
|
+
query: {},
|
|
415
|
+
props: { tenantId: PROJECT_ID },
|
|
416
|
+
});
|
|
417
|
+
|
|
418
|
+
expect(captured).toEqual([
|
|
419
|
+
{
|
|
420
|
+
subject: "alert",
|
|
421
|
+
modelName: "Alert State",
|
|
422
|
+
id: STATE_ID.toString(),
|
|
423
|
+
service: "AlertStateService",
|
|
424
|
+
},
|
|
425
|
+
{
|
|
426
|
+
subject: "alert",
|
|
427
|
+
modelName: "Alert Severity",
|
|
428
|
+
id: SEVERITY_ID.toString(),
|
|
429
|
+
service: "AlertSeverityService",
|
|
430
|
+
},
|
|
431
|
+
{
|
|
432
|
+
subject: "alert",
|
|
433
|
+
modelName: "Monitor Status",
|
|
434
|
+
id: MONITOR_STATUS_ID.toString(),
|
|
435
|
+
service: "MonitorStatusService",
|
|
436
|
+
},
|
|
437
|
+
]);
|
|
438
|
+
});
|
|
439
|
+
});
|
|
440
|
+
|
|
441
|
+
describe("ScheduledMaintenanceService", () => {
|
|
442
|
+
function mockScheduledState(): void {
|
|
443
|
+
const scheduledState: ScheduledMaintenanceState =
|
|
444
|
+
new ScheduledMaintenanceState();
|
|
445
|
+
scheduledState._id = STATE_ID.toString();
|
|
446
|
+
jest
|
|
447
|
+
.spyOn(ScheduledMaintenanceStateService, "findOneBy")
|
|
448
|
+
.mockResolvedValue(scheduledState as never);
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
test("create checks the monitor status it switches monitors to", async () => {
|
|
452
|
+
mockScheduledState();
|
|
453
|
+
spyOnValidator();
|
|
454
|
+
jest
|
|
455
|
+
.spyOn(ProjectService, "incrementAndGetScheduledMaintenanceCounter")
|
|
456
|
+
.mockResolvedValue({ counter: 1, prefix: undefined } as never);
|
|
457
|
+
|
|
458
|
+
await callHook(ScheduledMaintenanceService, "onBeforeCreate", {
|
|
459
|
+
data: {
|
|
460
|
+
title: "test",
|
|
461
|
+
changeMonitorStatusToId: MONITOR_STATUS_ID,
|
|
462
|
+
} as ScheduledMaintenance,
|
|
463
|
+
props: { tenantId: PROJECT_ID },
|
|
464
|
+
});
|
|
465
|
+
|
|
466
|
+
expect(captured).toEqual([
|
|
467
|
+
{
|
|
468
|
+
subject: "scheduled maintenance event",
|
|
469
|
+
modelName: "Monitor Status",
|
|
470
|
+
id: MONITOR_STATUS_ID.toString(),
|
|
471
|
+
service: "MonitorStatusService",
|
|
472
|
+
},
|
|
473
|
+
]);
|
|
474
|
+
});
|
|
475
|
+
|
|
476
|
+
test("create is rejected, and burns no event number, when the status is foreign", async () => {
|
|
477
|
+
mockScheduledState();
|
|
478
|
+
spyOnValidator(true);
|
|
479
|
+
const counter: jest.Mock = jest.fn() as unknown as jest.Mock;
|
|
480
|
+
jest
|
|
481
|
+
.spyOn(ProjectService, "incrementAndGetScheduledMaintenanceCounter")
|
|
482
|
+
.mockImplementation(counter as never);
|
|
483
|
+
|
|
484
|
+
await expect(
|
|
485
|
+
callHook(ScheduledMaintenanceService, "onBeforeCreate", {
|
|
486
|
+
data: {
|
|
487
|
+
title: "test",
|
|
488
|
+
changeMonitorStatusToId: MONITOR_STATUS_ID,
|
|
489
|
+
} as ScheduledMaintenance,
|
|
490
|
+
props: { tenantId: PROJECT_ID },
|
|
491
|
+
}),
|
|
492
|
+
).rejects.toThrow("belong to a different project");
|
|
493
|
+
|
|
494
|
+
expect(counter).not.toHaveBeenCalled();
|
|
495
|
+
});
|
|
496
|
+
|
|
497
|
+
test("update checks the state and the monitor status", async () => {
|
|
498
|
+
spyOnValidator();
|
|
499
|
+
|
|
500
|
+
await callHook(ScheduledMaintenanceService, "onBeforeUpdate", {
|
|
501
|
+
data: {
|
|
502
|
+
currentScheduledMaintenanceStateId: STATE_ID,
|
|
503
|
+
changeMonitorStatusToId: MONITOR_STATUS_ID,
|
|
504
|
+
},
|
|
505
|
+
query: {},
|
|
506
|
+
props: { tenantId: PROJECT_ID },
|
|
507
|
+
});
|
|
508
|
+
|
|
509
|
+
expect(captured).toEqual([
|
|
510
|
+
{
|
|
511
|
+
subject: "scheduled maintenance event",
|
|
512
|
+
modelName: "Scheduled Maintenance State",
|
|
513
|
+
id: STATE_ID.toString(),
|
|
514
|
+
service: "ScheduledMaintenanceStateService",
|
|
515
|
+
},
|
|
516
|
+
{
|
|
517
|
+
subject: "scheduled maintenance event",
|
|
518
|
+
modelName: "Monitor Status",
|
|
519
|
+
id: MONITOR_STATUS_ID.toString(),
|
|
520
|
+
service: "MonitorStatusService",
|
|
521
|
+
},
|
|
522
|
+
]);
|
|
523
|
+
});
|
|
524
|
+
});
|
|
525
|
+
|
|
526
|
+
describe("IncidentTemplateService", () => {
|
|
527
|
+
test("create checks every reference the template copies onto its incidents", async () => {
|
|
528
|
+
spyOnValidator();
|
|
529
|
+
|
|
530
|
+
await callHook(IncidentTemplateService, "onBeforeCreate", {
|
|
531
|
+
data: {
|
|
532
|
+
templateName: "test",
|
|
533
|
+
initialIncidentStateId: STATE_ID,
|
|
534
|
+
incidentSeverityId: SEVERITY_ID,
|
|
535
|
+
changeMonitorStatusToId: MONITOR_STATUS_ID,
|
|
536
|
+
} as IncidentTemplate,
|
|
537
|
+
props: { tenantId: PROJECT_ID },
|
|
538
|
+
});
|
|
539
|
+
|
|
540
|
+
expect(captured).toEqual([
|
|
541
|
+
{
|
|
542
|
+
subject: "incident template",
|
|
543
|
+
modelName: "Incident State",
|
|
544
|
+
id: STATE_ID.toString(),
|
|
545
|
+
service: "IncidentStateService",
|
|
546
|
+
},
|
|
547
|
+
{
|
|
548
|
+
subject: "incident template",
|
|
549
|
+
modelName: "Incident Severity",
|
|
550
|
+
id: SEVERITY_ID.toString(),
|
|
551
|
+
service: "IncidentSeverityService",
|
|
552
|
+
},
|
|
553
|
+
{
|
|
554
|
+
subject: "incident template",
|
|
555
|
+
modelName: "Monitor Status",
|
|
556
|
+
id: MONITOR_STATUS_ID.toString(),
|
|
557
|
+
service: "MonitorStatusService",
|
|
558
|
+
},
|
|
559
|
+
]);
|
|
560
|
+
});
|
|
561
|
+
|
|
562
|
+
test("update checks the same references", async () => {
|
|
563
|
+
spyOnValidator();
|
|
564
|
+
|
|
565
|
+
await callHook(IncidentTemplateService, "onBeforeUpdate", {
|
|
566
|
+
data: { incidentSeverityId: SEVERITY_ID },
|
|
567
|
+
query: {},
|
|
568
|
+
props: { tenantId: PROJECT_ID },
|
|
569
|
+
});
|
|
570
|
+
|
|
571
|
+
expect(captured).toEqual([
|
|
572
|
+
{
|
|
573
|
+
subject: "incident template",
|
|
574
|
+
modelName: "Incident Severity",
|
|
575
|
+
id: SEVERITY_ID.toString(),
|
|
576
|
+
service: "IncidentSeverityService",
|
|
577
|
+
},
|
|
578
|
+
]);
|
|
579
|
+
});
|
|
580
|
+
|
|
581
|
+
test("create is rejected when a reference is foreign", async () => {
|
|
582
|
+
spyOnValidator(true);
|
|
583
|
+
|
|
584
|
+
await expect(
|
|
585
|
+
callHook(IncidentTemplateService, "onBeforeCreate", {
|
|
586
|
+
data: {
|
|
587
|
+
templateName: "test",
|
|
588
|
+
incidentSeverityId: SEVERITY_ID,
|
|
589
|
+
} as IncidentTemplate,
|
|
590
|
+
props: { tenantId: PROJECT_ID },
|
|
591
|
+
}),
|
|
592
|
+
).rejects.toThrow("belong to a different project");
|
|
593
|
+
});
|
|
594
|
+
});
|
|
595
|
+
|
|
596
|
+
describe("ScheduledMaintenanceTemplateService", () => {
|
|
597
|
+
test("create checks the monitor status the template carries", async () => {
|
|
598
|
+
spyOnValidator();
|
|
599
|
+
|
|
600
|
+
await callHook(ScheduledMaintenanceTemplateService, "onBeforeCreate", {
|
|
601
|
+
data: {
|
|
602
|
+
templateName: "test",
|
|
603
|
+
title: "test",
|
|
604
|
+
description: "test",
|
|
605
|
+
changeMonitorStatusToId: MONITOR_STATUS_ID,
|
|
606
|
+
} as ScheduledMaintenanceTemplate,
|
|
607
|
+
props: { tenantId: PROJECT_ID },
|
|
608
|
+
});
|
|
609
|
+
|
|
610
|
+
expect(captured).toEqual([
|
|
611
|
+
{
|
|
612
|
+
subject: "scheduled maintenance template",
|
|
613
|
+
modelName: "Monitor Status",
|
|
614
|
+
id: MONITOR_STATUS_ID.toString(),
|
|
615
|
+
service: "MonitorStatusService",
|
|
616
|
+
},
|
|
617
|
+
]);
|
|
618
|
+
});
|
|
619
|
+
|
|
620
|
+
test("create is rejected when the status is foreign", async () => {
|
|
621
|
+
spyOnValidator(true);
|
|
622
|
+
|
|
623
|
+
await expect(
|
|
624
|
+
callHook(ScheduledMaintenanceTemplateService, "onBeforeCreate", {
|
|
625
|
+
data: {
|
|
626
|
+
templateName: "test",
|
|
627
|
+
title: "test",
|
|
628
|
+
description: "test",
|
|
629
|
+
changeMonitorStatusToId: MONITOR_STATUS_ID,
|
|
630
|
+
} as ScheduledMaintenanceTemplate,
|
|
631
|
+
props: { tenantId: PROJECT_ID },
|
|
632
|
+
}),
|
|
633
|
+
).rejects.toThrow("belong to a different project");
|
|
634
|
+
});
|
|
635
|
+
});
|
|
636
|
+
|
|
637
|
+
describe("episodes", () => {
|
|
638
|
+
/*
|
|
639
|
+
* IncidentEpisode and AlertEpisode hold the same state and severity
|
|
640
|
+
* columns on equally NO ACTION foreign keys. Leaving them unguarded means
|
|
641
|
+
* a single API call re-creates the undeletable project the migration just
|
|
642
|
+
* repaired, and there is no second repair scheduled.
|
|
643
|
+
*/
|
|
644
|
+
test("incident episode create checks the severity", async () => {
|
|
645
|
+
const createdState: IncidentState = new IncidentState();
|
|
646
|
+
createdState._id = STATE_ID.toString();
|
|
647
|
+
jest
|
|
648
|
+
.spyOn(IncidentStateService, "findOneBy")
|
|
649
|
+
.mockResolvedValue(createdState as never);
|
|
650
|
+
jest
|
|
651
|
+
.spyOn(ProjectService, "incrementAndGetIncidentEpisodeCounter")
|
|
652
|
+
.mockResolvedValue({ counter: 1, prefix: undefined } as never);
|
|
653
|
+
spyOnValidator();
|
|
654
|
+
|
|
655
|
+
await callHook(IncidentEpisodeService, "onBeforeCreate", {
|
|
656
|
+
data: {
|
|
657
|
+
title: "test",
|
|
658
|
+
incidentSeverityId: SEVERITY_ID,
|
|
659
|
+
} as IncidentEpisode,
|
|
660
|
+
props: { tenantId: PROJECT_ID },
|
|
661
|
+
});
|
|
662
|
+
|
|
663
|
+
expect(captured).toEqual([
|
|
664
|
+
{
|
|
665
|
+
subject: "incident episode",
|
|
666
|
+
modelName: "Incident Severity",
|
|
667
|
+
id: SEVERITY_ID.toString(),
|
|
668
|
+
service: "IncidentSeverityService",
|
|
669
|
+
},
|
|
670
|
+
]);
|
|
671
|
+
});
|
|
672
|
+
|
|
673
|
+
test("incident episode update checks state and severity", async () => {
|
|
674
|
+
spyOnValidator();
|
|
675
|
+
|
|
676
|
+
await callHook(IncidentEpisodeService, "onBeforeUpdate", {
|
|
677
|
+
data: {
|
|
678
|
+
currentIncidentStateId: STATE_ID,
|
|
679
|
+
incidentSeverityId: SEVERITY_ID,
|
|
680
|
+
},
|
|
681
|
+
query: {},
|
|
682
|
+
props: { tenantId: PROJECT_ID },
|
|
683
|
+
});
|
|
684
|
+
|
|
685
|
+
expect(captured).toEqual([
|
|
686
|
+
{
|
|
687
|
+
subject: "incident episode",
|
|
688
|
+
modelName: "Incident State",
|
|
689
|
+
id: STATE_ID.toString(),
|
|
690
|
+
service: "IncidentStateService",
|
|
691
|
+
},
|
|
692
|
+
{
|
|
693
|
+
subject: "incident episode",
|
|
694
|
+
modelName: "Incident Severity",
|
|
695
|
+
id: SEVERITY_ID.toString(),
|
|
696
|
+
service: "IncidentSeverityService",
|
|
697
|
+
},
|
|
698
|
+
]);
|
|
699
|
+
});
|
|
700
|
+
|
|
701
|
+
test("alert episode update checks state and severity", async () => {
|
|
702
|
+
spyOnValidator();
|
|
703
|
+
|
|
704
|
+
await callHook(AlertEpisodeService, "onBeforeUpdate", {
|
|
705
|
+
data: {
|
|
706
|
+
currentAlertStateId: STATE_ID,
|
|
707
|
+
alertSeverityId: SEVERITY_ID,
|
|
708
|
+
},
|
|
709
|
+
query: {},
|
|
710
|
+
props: { tenantId: PROJECT_ID },
|
|
711
|
+
});
|
|
712
|
+
|
|
713
|
+
expect(captured).toEqual([
|
|
714
|
+
{
|
|
715
|
+
subject: "alert episode",
|
|
716
|
+
modelName: "Alert State",
|
|
717
|
+
id: STATE_ID.toString(),
|
|
718
|
+
service: "AlertStateService",
|
|
719
|
+
},
|
|
720
|
+
{
|
|
721
|
+
subject: "alert episode",
|
|
722
|
+
modelName: "Alert Severity",
|
|
723
|
+
id: SEVERITY_ID.toString(),
|
|
724
|
+
service: "AlertSeverityService",
|
|
725
|
+
},
|
|
726
|
+
]);
|
|
727
|
+
});
|
|
728
|
+
|
|
729
|
+
test("alert episode create checks the severity", async () => {
|
|
730
|
+
const createdState: AlertState = new AlertState();
|
|
731
|
+
createdState._id = STATE_ID.toString();
|
|
732
|
+
jest
|
|
733
|
+
.spyOn(AlertStateService, "findOneBy")
|
|
734
|
+
.mockResolvedValue(createdState as never);
|
|
735
|
+
jest
|
|
736
|
+
.spyOn(ProjectService, "incrementAndGetAlertEpisodeCounter")
|
|
737
|
+
.mockResolvedValue({ counter: 1, prefix: undefined } as never);
|
|
738
|
+
spyOnValidator();
|
|
739
|
+
|
|
740
|
+
await callHook(AlertEpisodeService, "onBeforeCreate", {
|
|
741
|
+
data: {
|
|
742
|
+
title: "test",
|
|
743
|
+
alertSeverityId: SEVERITY_ID,
|
|
744
|
+
} as AlertEpisode,
|
|
745
|
+
props: { tenantId: PROJECT_ID },
|
|
746
|
+
});
|
|
747
|
+
|
|
748
|
+
expect(captured).toEqual([
|
|
749
|
+
{
|
|
750
|
+
subject: "alert episode",
|
|
751
|
+
modelName: "Alert Severity",
|
|
752
|
+
id: SEVERITY_ID.toString(),
|
|
753
|
+
service: "AlertSeverityService",
|
|
754
|
+
},
|
|
755
|
+
]);
|
|
756
|
+
});
|
|
757
|
+
});
|
|
758
|
+
|
|
759
|
+
describe("MonitorService", () => {
|
|
760
|
+
/*
|
|
761
|
+
* Monitor.currentMonitorStatusId is the one project-scoped reference that
|
|
762
|
+
* intentionally keeps ON DELETE NO ACTION, and it is writable by any
|
|
763
|
+
* project member — so it can block a project delete on its own. The
|
|
764
|
+
* 1785240000000 migration repaired the rows that existed then; this is
|
|
765
|
+
* what stops new ones.
|
|
766
|
+
*/
|
|
767
|
+
test("update checks currentMonitorStatusId", async () => {
|
|
768
|
+
spyOnValidator();
|
|
769
|
+
|
|
770
|
+
await callHook(MonitorService, "onBeforeUpdate", {
|
|
771
|
+
data: { currentMonitorStatusId: MONITOR_STATUS_ID },
|
|
772
|
+
query: {},
|
|
773
|
+
props: { tenantId: PROJECT_ID },
|
|
774
|
+
});
|
|
775
|
+
|
|
776
|
+
expect(captured).toEqual([
|
|
777
|
+
{
|
|
778
|
+
subject: "monitor",
|
|
779
|
+
modelName: "Monitor Status",
|
|
780
|
+
id: MONITOR_STATUS_ID.toString(),
|
|
781
|
+
service: "MonitorStatusService",
|
|
782
|
+
},
|
|
783
|
+
]);
|
|
784
|
+
});
|
|
785
|
+
|
|
786
|
+
test("update is rejected when the status belongs to another project", async () => {
|
|
787
|
+
spyOnValidator(true);
|
|
788
|
+
|
|
789
|
+
await expect(
|
|
790
|
+
callHook(MonitorService, "onBeforeUpdate", {
|
|
791
|
+
data: { currentMonitorStatusId: MONITOR_STATUS_ID },
|
|
792
|
+
query: {},
|
|
793
|
+
props: { tenantId: PROJECT_ID },
|
|
794
|
+
}),
|
|
795
|
+
).rejects.toThrow("belong to a different project");
|
|
796
|
+
});
|
|
797
|
+
|
|
798
|
+
test("update looks nothing up when neither monitorSteps nor the status is written", async () => {
|
|
799
|
+
spyOnValidator();
|
|
800
|
+
|
|
801
|
+
await callHook(MonitorService, "onBeforeUpdate", {
|
|
802
|
+
data: { description: "renamed" },
|
|
803
|
+
query: {},
|
|
804
|
+
props: { tenantId: PROJECT_ID },
|
|
805
|
+
});
|
|
806
|
+
|
|
807
|
+
expect(validatorCalls).toHaveLength(0);
|
|
808
|
+
});
|
|
809
|
+
});
|
|
810
|
+
});
|