@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
|
@@ -24,6 +24,10 @@ import Model from "../../Models/DatabaseModels/ScheduledMaintenance";
|
|
|
24
24
|
import ScheduledMaintenanceOwnerTeam from "../../Models/DatabaseModels/ScheduledMaintenanceOwnerTeam";
|
|
25
25
|
import ScheduledMaintenanceOwnerUser from "../../Models/DatabaseModels/ScheduledMaintenanceOwnerUser";
|
|
26
26
|
import ScheduledMaintenanceState from "../../Models/DatabaseModels/ScheduledMaintenanceState";
|
|
27
|
+
import MonitorStatusService from "./MonitorStatusService";
|
|
28
|
+
import ProjectScopedReferenceValidator, {
|
|
29
|
+
resolveReferenceId,
|
|
30
|
+
} from "../Utils/Database/ProjectScopedReferenceValidator";
|
|
27
31
|
import ScheduledMaintenanceStateTimeline from "../../Models/DatabaseModels/ScheduledMaintenanceStateTimeline";
|
|
28
32
|
import User from "../../Models/DatabaseModels/User";
|
|
29
33
|
import Recurring from "../../Types/Events/Recurring";
|
|
@@ -599,12 +603,91 @@ ${resourcesAffected ? `**Resources Affected:** ${resourcesAffected}` : ""}
|
|
|
599
603
|
}
|
|
600
604
|
}
|
|
601
605
|
|
|
606
|
+
await this.validateProjectScopedReferences(updateBy);
|
|
607
|
+
|
|
602
608
|
return {
|
|
603
609
|
updateBy,
|
|
604
610
|
carryForward: null,
|
|
605
611
|
};
|
|
606
612
|
}
|
|
607
613
|
|
|
614
|
+
/*
|
|
615
|
+
* An update can repoint a scheduled maintenance event at another project's
|
|
616
|
+
* state or monitor status just as easily as a create can, and the result is
|
|
617
|
+
* the same: the referenced project can no longer be deleted. Only the
|
|
618
|
+
* columns actually being written are checked, so ordinary updates cost no
|
|
619
|
+
* extra queries.
|
|
620
|
+
*/
|
|
621
|
+
private async validateProjectScopedReferences(
|
|
622
|
+
updateBy: UpdateBy<Model>,
|
|
623
|
+
): Promise<void> {
|
|
624
|
+
const stateId: ObjectID | string | undefined =
|
|
625
|
+
resolveReferenceId(updateBy.data.currentScheduledMaintenanceStateId) ||
|
|
626
|
+
resolveReferenceId(updateBy.data.currentScheduledMaintenanceState);
|
|
627
|
+
|
|
628
|
+
const monitorStatusId: ObjectID | string | undefined =
|
|
629
|
+
resolveReferenceId(updateBy.data.changeMonitorStatusToId) ||
|
|
630
|
+
resolveReferenceId(updateBy.data.changeMonitorStatusTo);
|
|
631
|
+
|
|
632
|
+
if (!stateId && !monitorStatusId) {
|
|
633
|
+
return;
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
/*
|
|
637
|
+
* Root/API updates do not always carry a tenantId, so fall back to the
|
|
638
|
+
* project of each event the query actually matches.
|
|
639
|
+
*/
|
|
640
|
+
const projectIds: Array<ObjectID> = updateBy.props.tenantId
|
|
641
|
+
? [updateBy.props.tenantId]
|
|
642
|
+
: await this.getProjectIdsForUpdateQuery(updateBy);
|
|
643
|
+
|
|
644
|
+
for (const projectId of projectIds) {
|
|
645
|
+
await ProjectScopedReferenceValidator.validateReferencesBelongToProject({
|
|
646
|
+
projectId: projectId,
|
|
647
|
+
subject: "scheduled maintenance event",
|
|
648
|
+
references: [
|
|
649
|
+
{
|
|
650
|
+
modelName: "Scheduled Maintenance State",
|
|
651
|
+
id: stateId,
|
|
652
|
+
service: ScheduledMaintenanceStateService,
|
|
653
|
+
},
|
|
654
|
+
{
|
|
655
|
+
modelName: "Monitor Status",
|
|
656
|
+
id: monitorStatusId,
|
|
657
|
+
service: MonitorStatusService,
|
|
658
|
+
},
|
|
659
|
+
],
|
|
660
|
+
});
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
private async getProjectIdsForUpdateQuery(
|
|
665
|
+
updateBy: UpdateBy<Model>,
|
|
666
|
+
): Promise<Array<ObjectID>> {
|
|
667
|
+
const scheduledMaintenanceEvents: Array<Model> = await this.findBy({
|
|
668
|
+
query: updateBy.query,
|
|
669
|
+
select: {
|
|
670
|
+
projectId: true,
|
|
671
|
+
},
|
|
672
|
+
limit: LIMIT_MAX,
|
|
673
|
+
skip: 0,
|
|
674
|
+
props: {
|
|
675
|
+
isRoot: true,
|
|
676
|
+
},
|
|
677
|
+
});
|
|
678
|
+
|
|
679
|
+
const projectIds: Dictionary<ObjectID> = {};
|
|
680
|
+
|
|
681
|
+
for (const scheduledMaintenance of scheduledMaintenanceEvents) {
|
|
682
|
+
if (scheduledMaintenance.projectId) {
|
|
683
|
+
projectIds[scheduledMaintenance.projectId.toString()] =
|
|
684
|
+
scheduledMaintenance.projectId;
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
return Object.values(projectIds);
|
|
689
|
+
}
|
|
690
|
+
|
|
608
691
|
@CaptureSpan()
|
|
609
692
|
protected override async onBeforeDelete(
|
|
610
693
|
deleteBy: DeleteBy<Model>,
|
|
@@ -758,6 +841,26 @@ ${resourcesAffected ? `**Resources Affected:** ${resourcesAffected}` : ""}
|
|
|
758
841
|
createBy.data.currentScheduledMaintenanceStateId =
|
|
759
842
|
scheduledMaintenanceState.id;
|
|
760
843
|
|
|
844
|
+
/*
|
|
845
|
+
* changeMonitorStatusToId comes straight from the API caller or a
|
|
846
|
+
* template, and nothing checked it belongs to this project. Persisting
|
|
847
|
+
* another project's id leaves that project undeletable. Runs before the
|
|
848
|
+
* counter increment so a rejected create does not burn an event number.
|
|
849
|
+
*/
|
|
850
|
+
await ProjectScopedReferenceValidator.validateReferencesBelongToProject({
|
|
851
|
+
projectId: projectId,
|
|
852
|
+
subject: "scheduled maintenance event",
|
|
853
|
+
references: [
|
|
854
|
+
{
|
|
855
|
+
modelName: "Monitor Status",
|
|
856
|
+
id:
|
|
857
|
+
resolveReferenceId(createBy.data.changeMonitorStatusToId) ||
|
|
858
|
+
resolveReferenceId(createBy.data.changeMonitorStatusTo),
|
|
859
|
+
service: MonitorStatusService,
|
|
860
|
+
},
|
|
861
|
+
],
|
|
862
|
+
});
|
|
863
|
+
|
|
761
864
|
const scheduledMaintenanceCounterResult: {
|
|
762
865
|
counter: number;
|
|
763
866
|
prefix: string | undefined;
|
|
@@ -6,6 +6,12 @@ import DatabaseCommonInteractionProps from "../../Types/BaseDatabase/DatabaseCom
|
|
|
6
6
|
import ObjectID from "../../Types/ObjectID";
|
|
7
7
|
import Typeof from "../../Types/Typeof";
|
|
8
8
|
import Model from "../../Models/DatabaseModels/ScheduledMaintenanceTemplate";
|
|
9
|
+
import MonitorStatusService from "./MonitorStatusService";
|
|
10
|
+
import Dictionary from "../../Types/Dictionary";
|
|
11
|
+
import ProjectScopedReferenceValidator, {
|
|
12
|
+
ProjectScopedReference,
|
|
13
|
+
resolveReferenceId,
|
|
14
|
+
} from "../Utils/Database/ProjectScopedReferenceValidator";
|
|
9
15
|
import ScheduledMaintenanceTemplateOwnerTeam from "../../Models/DatabaseModels/ScheduledMaintenanceTemplateOwnerTeam";
|
|
10
16
|
import ScheduledMaintenanceTemplateOwnerUser from "../../Models/DatabaseModels/ScheduledMaintenanceTemplateOwnerUser";
|
|
11
17
|
import CreateBy from "../Types/Database/CreateBy";
|
|
@@ -113,6 +119,12 @@ export class Service extends DatabaseService<Model> {
|
|
|
113
119
|
): Promise<OnCreate<Model>> {
|
|
114
120
|
this.validateEventTemplate(createBy.data);
|
|
115
121
|
|
|
122
|
+
await ProjectScopedReferenceValidator.validateReferencesBelongToProject({
|
|
123
|
+
projectId: createBy.props.tenantId || createBy.data.projectId,
|
|
124
|
+
subject: "scheduled maintenance template",
|
|
125
|
+
references: this.getProjectScopedReferences(createBy.data),
|
|
126
|
+
});
|
|
127
|
+
|
|
116
128
|
if (createBy.data.isRecurringEvent) {
|
|
117
129
|
// if all is good then the next scheduled at time should be set.
|
|
118
130
|
createBy.data.scheduleNextEventAt = this.getNextEventTime({
|
|
@@ -253,12 +265,90 @@ export class Service extends DatabaseService<Model> {
|
|
|
253
265
|
|
|
254
266
|
updateBy.data = newTemplate;
|
|
255
267
|
|
|
268
|
+
await this.validateProjectScopedReferences(updateBy);
|
|
269
|
+
|
|
256
270
|
return {
|
|
257
271
|
updateBy: updateBy,
|
|
258
272
|
carryForward: false,
|
|
259
273
|
};
|
|
260
274
|
}
|
|
261
275
|
|
|
276
|
+
/*
|
|
277
|
+
* A template is copied onto every event created from it, so an id belonging
|
|
278
|
+
* to another project here becomes a cross-project reference on each of those
|
|
279
|
+
* events — and the referenced project can then no longer be deleted.
|
|
280
|
+
*/
|
|
281
|
+
private async validateProjectScopedReferences(
|
|
282
|
+
updateBy: UpdateBy<Model>,
|
|
283
|
+
): Promise<void> {
|
|
284
|
+
const references: Array<ProjectScopedReference> =
|
|
285
|
+
this.getProjectScopedReferences(updateBy.data);
|
|
286
|
+
|
|
287
|
+
if (
|
|
288
|
+
references.every((reference: ProjectScopedReference) => {
|
|
289
|
+
return !reference.id;
|
|
290
|
+
})
|
|
291
|
+
) {
|
|
292
|
+
return;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
/*
|
|
296
|
+
* Root/API updates do not always carry a tenantId, so fall back to the
|
|
297
|
+
* project of each template the query actually matches.
|
|
298
|
+
*/
|
|
299
|
+
const projectIds: Array<ObjectID> = updateBy.props.tenantId
|
|
300
|
+
? [updateBy.props.tenantId]
|
|
301
|
+
: await this.getProjectIdsForUpdateQuery(updateBy);
|
|
302
|
+
|
|
303
|
+
for (const projectId of projectIds) {
|
|
304
|
+
await ProjectScopedReferenceValidator.validateReferencesBelongToProject({
|
|
305
|
+
projectId: projectId,
|
|
306
|
+
subject: "scheduled maintenance template",
|
|
307
|
+
references: references,
|
|
308
|
+
});
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
private getProjectScopedReferences(
|
|
313
|
+
data: Model | QueryDeepPartialEntity<Model>,
|
|
314
|
+
): Array<ProjectScopedReference> {
|
|
315
|
+
return [
|
|
316
|
+
{
|
|
317
|
+
modelName: "Monitor Status",
|
|
318
|
+
id:
|
|
319
|
+
resolveReferenceId(data.changeMonitorStatusToId) ||
|
|
320
|
+
resolveReferenceId(data.changeMonitorStatusTo),
|
|
321
|
+
service: MonitorStatusService,
|
|
322
|
+
},
|
|
323
|
+
];
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
private async getProjectIdsForUpdateQuery(
|
|
327
|
+
updateBy: UpdateBy<Model>,
|
|
328
|
+
): Promise<Array<ObjectID>> {
|
|
329
|
+
const templates: Array<Model> = await this.findBy({
|
|
330
|
+
query: updateBy.query,
|
|
331
|
+
select: {
|
|
332
|
+
projectId: true,
|
|
333
|
+
},
|
|
334
|
+
limit: LIMIT_MAX,
|
|
335
|
+
skip: 0,
|
|
336
|
+
props: {
|
|
337
|
+
isRoot: true,
|
|
338
|
+
},
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
const projectIds: Dictionary<ObjectID> = {};
|
|
342
|
+
|
|
343
|
+
for (const template of templates) {
|
|
344
|
+
if (template.projectId) {
|
|
345
|
+
projectIds[template.projectId.toString()] = template.projectId;
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
return Object.values(projectIds);
|
|
350
|
+
}
|
|
351
|
+
|
|
262
352
|
@CaptureSpan()
|
|
263
353
|
protected override async onCreateSuccess(
|
|
264
354
|
onCreate: OnCreate<Model>,
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import CreateBy from "../Types/Database/CreateBy";
|
|
2
|
+
import DatabaseCommonInteractionProps from "../../Types/BaseDatabase/DatabaseCommonInteractionProps";
|
|
2
3
|
import DeleteBy from "../Types/Database/DeleteBy";
|
|
3
4
|
import { OnCreate, OnDelete, OnUpdate } from "../Types/Database/Hooks";
|
|
5
|
+
import Query from "../Types/Database/Query";
|
|
4
6
|
import QueryHelper from "../Types/Database/QueryHelper";
|
|
5
7
|
import UpdateBy from "../Types/Database/UpdateBy";
|
|
6
8
|
import DatabaseService from "./DatabaseService";
|
|
@@ -10,6 +12,7 @@ import LIMIT_MAX from "../../Types/Database/LimitMax";
|
|
|
10
12
|
import BadDataException from "../../Types/Exception/BadDataException";
|
|
11
13
|
import ObjectID from "../../Types/ObjectID";
|
|
12
14
|
import PositiveNumber from "../../Types/PositiveNumber";
|
|
15
|
+
import StatusPageGroupTreeUtil from "../../Utils/StatusPage/GroupTree";
|
|
13
16
|
import Model from "../../Models/DatabaseModels/StatusPageGroup";
|
|
14
17
|
|
|
15
18
|
export class Service extends DatabaseService<Model> {
|
|
@@ -25,6 +28,14 @@ export class Service extends DatabaseService<Model> {
|
|
|
25
28
|
throw new BadDataException("Status Page Group statusPageId is required");
|
|
26
29
|
}
|
|
27
30
|
|
|
31
|
+
if (createBy.data.parentStatusPageGroupId) {
|
|
32
|
+
await this.assertParentIsValid({
|
|
33
|
+
statusPageGroupId: null,
|
|
34
|
+
parentStatusPageGroupId: createBy.data.parentStatusPageGroupId,
|
|
35
|
+
statusPageId: createBy.data.statusPageId,
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
|
|
28
39
|
if (!createBy.data.order) {
|
|
29
40
|
const count: PositiveNumber = await this.countBy({
|
|
30
41
|
query: {
|
|
@@ -101,10 +112,185 @@ export class Service extends DatabaseService<Model> {
|
|
|
101
112
|
};
|
|
102
113
|
}
|
|
103
114
|
|
|
115
|
+
/*
|
|
116
|
+
* The hierarchy hooks run BEFORE DatabaseService applies tenant scoping to
|
|
117
|
+
* the caller's query, so reading the raw client query with props.isRoot
|
|
118
|
+
* would hand the hook rows from other projects. Re-apply the caller's tenant
|
|
119
|
+
* so validation can never look at a row outside the caller's project.
|
|
120
|
+
*/
|
|
121
|
+
private scopeQueryToCallerTenant(
|
|
122
|
+
query: Query<Model>,
|
|
123
|
+
props: DatabaseCommonInteractionProps,
|
|
124
|
+
): Query<Model> {
|
|
125
|
+
if (props.isRoot || !props.tenantId) {
|
|
126
|
+
return query;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return {
|
|
130
|
+
...query,
|
|
131
|
+
projectId: props.tenantId,
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/*
|
|
136
|
+
* A parent has to be a real group on the same status page, and the move must
|
|
137
|
+
* not build a loop (A under B under A) or nest deeper than the tree utils
|
|
138
|
+
* are willing to walk. A loop would make every rolled up number on the page
|
|
139
|
+
* meaningless and the group itself unreachable in the rendered tree.
|
|
140
|
+
*/
|
|
141
|
+
private async assertParentIsValid(data: {
|
|
142
|
+
statusPageGroupId: ObjectID | null;
|
|
143
|
+
parentStatusPageGroupId: ObjectID;
|
|
144
|
+
statusPageId: ObjectID;
|
|
145
|
+
}): Promise<void> {
|
|
146
|
+
if (
|
|
147
|
+
data.statusPageGroupId &&
|
|
148
|
+
data.statusPageGroupId.toString() ===
|
|
149
|
+
data.parentStatusPageGroupId.toString()
|
|
150
|
+
) {
|
|
151
|
+
throw new BadDataException("A group cannot be its own parent group.");
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
const parent: Model | null = await this.findOneById({
|
|
155
|
+
id: data.parentStatusPageGroupId,
|
|
156
|
+
select: {
|
|
157
|
+
_id: true,
|
|
158
|
+
statusPageId: true,
|
|
159
|
+
},
|
|
160
|
+
props: {
|
|
161
|
+
isRoot: true,
|
|
162
|
+
},
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
if (!parent) {
|
|
166
|
+
throw new BadDataException("Parent group not found.");
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
if (parent.statusPageId?.toString() !== data.statusPageId.toString()) {
|
|
170
|
+
throw new BadDataException(
|
|
171
|
+
"Parent group must belong to the same status page.",
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
const groupsOnStatusPage: Array<Model> = await this.findBy({
|
|
176
|
+
query: {
|
|
177
|
+
statusPageId: data.statusPageId,
|
|
178
|
+
},
|
|
179
|
+
select: {
|
|
180
|
+
_id: true,
|
|
181
|
+
parentStatusPageGroupId: true,
|
|
182
|
+
},
|
|
183
|
+
limit: LIMIT_MAX,
|
|
184
|
+
skip: 0,
|
|
185
|
+
props: {
|
|
186
|
+
isRoot: true,
|
|
187
|
+
},
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
const ancestorsOfParent: Array<Model> =
|
|
191
|
+
StatusPageGroupTreeUtil.getAncestorGroups({
|
|
192
|
+
statusPageGroup: parent,
|
|
193
|
+
statusPageGroups: groupsOnStatusPage,
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
if (
|
|
197
|
+
data.statusPageGroupId &&
|
|
198
|
+
ancestorsOfParent.some((ancestor: Model) => {
|
|
199
|
+
return ancestor._id?.toString() === data.statusPageGroupId!.toString();
|
|
200
|
+
})
|
|
201
|
+
) {
|
|
202
|
+
throw new BadDataException(
|
|
203
|
+
"This group cannot be nested under one of its own sub groups.",
|
|
204
|
+
);
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/*
|
|
208
|
+
* Depth of the parent chain, plus the group being placed. A group that is
|
|
209
|
+
* moved carries its own subtree along, so the deepest descendant has to
|
|
210
|
+
* fit under the limit too.
|
|
211
|
+
*/
|
|
212
|
+
const depthOfNewParent: number = ancestorsOfParent.length + 1;
|
|
213
|
+
|
|
214
|
+
let deepestDescendantOffset: number = 0;
|
|
215
|
+
|
|
216
|
+
if (data.statusPageGroupId) {
|
|
217
|
+
const group: Model | undefined = groupsOnStatusPage.find(
|
|
218
|
+
(item: Model) => {
|
|
219
|
+
return item._id?.toString() === data.statusPageGroupId!.toString();
|
|
220
|
+
},
|
|
221
|
+
);
|
|
222
|
+
|
|
223
|
+
if (group) {
|
|
224
|
+
for (const descendant of StatusPageGroupTreeUtil.getDescendantGroups({
|
|
225
|
+
statusPageGroup: group,
|
|
226
|
+
statusPageGroups: groupsOnStatusPage,
|
|
227
|
+
})) {
|
|
228
|
+
const relativeDepth: number =
|
|
229
|
+
StatusPageGroupTreeUtil.getDepth({
|
|
230
|
+
statusPageGroup: descendant,
|
|
231
|
+
statusPageGroups: groupsOnStatusPage,
|
|
232
|
+
}) -
|
|
233
|
+
StatusPageGroupTreeUtil.getDepth({
|
|
234
|
+
statusPageGroup: group,
|
|
235
|
+
statusPageGroups: groupsOnStatusPage,
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
deepestDescendantOffset = Math.max(
|
|
239
|
+
deepestDescendantOffset,
|
|
240
|
+
relativeDepth,
|
|
241
|
+
);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
if (
|
|
247
|
+
depthOfNewParent + deepestDescendantOffset >=
|
|
248
|
+
StatusPageGroupTreeUtil.MaxNestingDepth
|
|
249
|
+
) {
|
|
250
|
+
throw new BadDataException(
|
|
251
|
+
`Status page groups can only be nested ${StatusPageGroupTreeUtil.MaxNestingDepth} levels deep.`,
|
|
252
|
+
);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
104
256
|
@CaptureSpan()
|
|
105
257
|
protected override async onBeforeUpdate(
|
|
106
258
|
updateBy: UpdateBy<Model>,
|
|
107
259
|
): Promise<OnUpdate<Model>> {
|
|
260
|
+
const newParentIdValue: unknown = (updateBy.data as any)[
|
|
261
|
+
"parentStatusPageGroupId"
|
|
262
|
+
];
|
|
263
|
+
|
|
264
|
+
// detaching a group (parent set to null) has no parent to validate.
|
|
265
|
+
if (newParentIdValue) {
|
|
266
|
+
const newParentId: ObjectID = new ObjectID(newParentIdValue.toString());
|
|
267
|
+
|
|
268
|
+
const groupsBeingUpdated: Array<Model> = await this.findBy({
|
|
269
|
+
query: this.scopeQueryToCallerTenant(updateBy.query, updateBy.props),
|
|
270
|
+
select: {
|
|
271
|
+
_id: true,
|
|
272
|
+
statusPageId: true,
|
|
273
|
+
},
|
|
274
|
+
limit: LIMIT_MAX,
|
|
275
|
+
skip: 0,
|
|
276
|
+
props: {
|
|
277
|
+
isRoot: true,
|
|
278
|
+
},
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
for (const group of groupsBeingUpdated) {
|
|
282
|
+
if (!group.id || !group.statusPageId) {
|
|
283
|
+
continue;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
await this.assertParentIsValid({
|
|
287
|
+
statusPageGroupId: group.id,
|
|
288
|
+
parentStatusPageGroupId: newParentId,
|
|
289
|
+
statusPageId: group.statusPageId,
|
|
290
|
+
});
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
108
294
|
if (updateBy.data.order && !updateBy.props.isRoot && updateBy.query._id) {
|
|
109
295
|
const group: Model | null = await this.findOneBy({
|
|
110
296
|
query: {
|
|
@@ -1,10 +1,143 @@
|
|
|
1
1
|
import DatabaseService from "./DatabaseService";
|
|
2
2
|
import Model from "../../Models/DatabaseModels/TraceDropFilter";
|
|
3
|
+
import CreateBy from "../Types/Database/CreateBy";
|
|
4
|
+
import UpdateBy from "../Types/Database/UpdateBy";
|
|
5
|
+
import { OnCreate, OnUpdate } from "../Types/Database/Hooks";
|
|
6
|
+
import LIMIT_MAX from "../../Types/Database/LimitMax";
|
|
7
|
+
import ObjectID from "../../Types/ObjectID";
|
|
8
|
+
import OneUptimeDate from "../../Types/Date";
|
|
9
|
+
import PartialEntity from "../../Types/Database/PartialEntity";
|
|
10
|
+
import {
|
|
11
|
+
DropFilterCandidate,
|
|
12
|
+
DropFilterValidationOptions,
|
|
13
|
+
isSqlExpressionValue,
|
|
14
|
+
validateDropFilter,
|
|
15
|
+
} from "../Utils/DropFilterValidation";
|
|
16
|
+
|
|
17
|
+
const VALIDATION_OPTIONS: DropFilterValidationOptions = {
|
|
18
|
+
recordNoun: "spans",
|
|
19
|
+
};
|
|
3
20
|
|
|
4
21
|
export class Service extends DatabaseService<Model> {
|
|
5
22
|
public constructor() {
|
|
6
23
|
super(Model);
|
|
7
24
|
}
|
|
25
|
+
|
|
26
|
+
protected override async onBeforeCreate(
|
|
27
|
+
createBy: CreateBy<Model>,
|
|
28
|
+
): Promise<OnCreate<Model>> {
|
|
29
|
+
validateDropFilter(
|
|
30
|
+
{
|
|
31
|
+
action: createBy.data.action,
|
|
32
|
+
samplePercentage: createBy.data.samplePercentage,
|
|
33
|
+
filterQuery: createBy.data.filterQuery as string | undefined,
|
|
34
|
+
},
|
|
35
|
+
VALIDATION_OPTIONS,
|
|
36
|
+
);
|
|
37
|
+
|
|
38
|
+
return { createBy, carryForward: null };
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
protected override async onBeforeUpdate(
|
|
42
|
+
updateBy: UpdateBy<Model>,
|
|
43
|
+
): Promise<OnUpdate<Model>> {
|
|
44
|
+
/*
|
|
45
|
+
* An update can make a row invalid without naming every field: flipping
|
|
46
|
+
* `action` to "sample" while the stored `samplePercentage` is null, or
|
|
47
|
+
* blanking `filterQuery` on a row whose action is already "drop". So
|
|
48
|
+
* validate the MERGED row, not the incoming partial.
|
|
49
|
+
*
|
|
50
|
+
* Only pay for the SELECT when the update actually touches one of the
|
|
51
|
+
* three fields that can break the row. Drop-filter edits are rare,
|
|
52
|
+
* human-driven config changes — this is not a hot path.
|
|
53
|
+
*/
|
|
54
|
+
const incomingAction: unknown = updateBy.data.action;
|
|
55
|
+
const incomingSamplePercentage: unknown = updateBy.data.samplePercentage;
|
|
56
|
+
const incomingFilterQuery: unknown = updateBy.data.filterQuery;
|
|
57
|
+
|
|
58
|
+
const touchesValidatedFields: boolean =
|
|
59
|
+
incomingAction !== undefined ||
|
|
60
|
+
incomingSamplePercentage !== undefined ||
|
|
61
|
+
incomingFilterQuery !== undefined;
|
|
62
|
+
|
|
63
|
+
if (!touchesValidatedFields) {
|
|
64
|
+
return { updateBy, carryForward: null };
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
if (
|
|
68
|
+
isSqlExpressionValue(incomingAction) ||
|
|
69
|
+
isSqlExpressionValue(incomingSamplePercentage) ||
|
|
70
|
+
isSqlExpressionValue(incomingFilterQuery)
|
|
71
|
+
) {
|
|
72
|
+
// Cannot evaluate a raw SQL expression here. See isSqlExpressionValue.
|
|
73
|
+
return { updateBy, carryForward: null };
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const existingRows: Array<Model> = await this.findBy({
|
|
77
|
+
query: updateBy.query,
|
|
78
|
+
skip: 0,
|
|
79
|
+
limit: LIMIT_MAX,
|
|
80
|
+
select: {
|
|
81
|
+
_id: true,
|
|
82
|
+
action: true,
|
|
83
|
+
samplePercentage: true,
|
|
84
|
+
filterQuery: true,
|
|
85
|
+
},
|
|
86
|
+
props: {
|
|
87
|
+
isRoot: true,
|
|
88
|
+
},
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
for (const existing of existingRows) {
|
|
92
|
+
const merged: DropFilterCandidate = {
|
|
93
|
+
action:
|
|
94
|
+
incomingAction !== undefined
|
|
95
|
+
? (incomingAction as string | null)
|
|
96
|
+
: existing.action,
|
|
97
|
+
samplePercentage:
|
|
98
|
+
incomingSamplePercentage !== undefined
|
|
99
|
+
? (incomingSamplePercentage as number | null)
|
|
100
|
+
: existing.samplePercentage,
|
|
101
|
+
filterQuery:
|
|
102
|
+
incomingFilterQuery !== undefined
|
|
103
|
+
? (incomingFilterQuery as string | null)
|
|
104
|
+
: (existing.filterQuery as string | null),
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
validateDropFilter(merged, VALIDATION_OPTIONS);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return { updateBy, carryForward: null };
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/*
|
|
114
|
+
* Ingest-path counter flush: add `count` drops to this filter's running
|
|
115
|
+
* total and stamp `lastDroppedAt`, in one atomic statement.
|
|
116
|
+
*
|
|
117
|
+
* Called from the telemetry ingest workers on a throttle (many dropped
|
|
118
|
+
* spans batched into one UPDATE), never once per record, and never on the
|
|
119
|
+
* request path. Runs no hooks and does not bump `version`, so it cannot
|
|
120
|
+
* conflict with a human editing the same filter in the dashboard.
|
|
121
|
+
*
|
|
122
|
+
* See App/FeatureSet/Telemetry/Utils/DropFilterDropRecorder.ts.
|
|
123
|
+
*/
|
|
124
|
+
public async addToDroppedCount(data: {
|
|
125
|
+
id: ObjectID;
|
|
126
|
+
count: number;
|
|
127
|
+
lastDroppedAt?: Date | undefined;
|
|
128
|
+
}): Promise<void> {
|
|
129
|
+
if (!data.count || data.count <= 0) {
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
await this.atomicAddToColumnsByIdWithoutHooks({
|
|
134
|
+
id: data.id,
|
|
135
|
+
add: { droppedCount: data.count },
|
|
136
|
+
set: {
|
|
137
|
+
lastDroppedAt: data.lastDroppedAt || OneUptimeDate.getCurrentDate(),
|
|
138
|
+
} as PartialEntity<Model>,
|
|
139
|
+
});
|
|
140
|
+
}
|
|
8
141
|
}
|
|
9
142
|
|
|
10
143
|
export default new Service();
|
|
@@ -48,6 +48,18 @@ export default class ApiDelete extends ComponentCode {
|
|
|
48
48
|
headers: args["request-headers"] as Dictionary<string>,
|
|
49
49
|
});
|
|
50
50
|
|
|
51
|
+
/*
|
|
52
|
+
* On the server API resolves with an HTTPErrorResponse instead of
|
|
53
|
+
* throwing, so the catch below never sees an HTTP error - a 4xx/5xx used
|
|
54
|
+
* to take the success port.
|
|
55
|
+
*/
|
|
56
|
+
if (apiResult instanceof HTTPErrorResponse) {
|
|
57
|
+
return Promise.resolve({
|
|
58
|
+
returnValues: ApiComponentUtils.getReturnValues(apiResult),
|
|
59
|
+
executePort: result.errorPort,
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
51
63
|
return Promise.resolve({
|
|
52
64
|
returnValues: ApiComponentUtils.getReturnValues(apiResult),
|
|
53
65
|
executePort: result.successPort,
|
|
@@ -48,6 +48,18 @@ export default class ApiGet extends ComponentCode {
|
|
|
48
48
|
headers: args["request-headers"] as Dictionary<string>,
|
|
49
49
|
});
|
|
50
50
|
|
|
51
|
+
/*
|
|
52
|
+
* On the server API resolves with an HTTPErrorResponse instead of
|
|
53
|
+
* throwing, so the catch below never sees an HTTP error - a 4xx/5xx used
|
|
54
|
+
* to take the success port.
|
|
55
|
+
*/
|
|
56
|
+
if (apiResult instanceof HTTPErrorResponse) {
|
|
57
|
+
return Promise.resolve({
|
|
58
|
+
returnValues: ApiComponentUtils.getReturnValues(apiResult),
|
|
59
|
+
executePort: result.errorPort,
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
51
63
|
return Promise.resolve({
|
|
52
64
|
returnValues: ApiComponentUtils.getReturnValues(apiResult),
|
|
53
65
|
executePort: result.successPort,
|
|
@@ -48,6 +48,18 @@ export default class ApiPut extends ComponentCode {
|
|
|
48
48
|
headers: args["request-headers"] as Dictionary<string>,
|
|
49
49
|
});
|
|
50
50
|
|
|
51
|
+
/*
|
|
52
|
+
* On the server API resolves with an HTTPErrorResponse instead of
|
|
53
|
+
* throwing, so the catch below never sees an HTTP error - a 4xx/5xx used
|
|
54
|
+
* to take the success port.
|
|
55
|
+
*/
|
|
56
|
+
if (apiResult instanceof HTTPErrorResponse) {
|
|
57
|
+
return Promise.resolve({
|
|
58
|
+
returnValues: ApiComponentUtils.getReturnValues(apiResult),
|
|
59
|
+
executePort: result.errorPort,
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
51
63
|
return Promise.resolve({
|
|
52
64
|
returnValues: ApiComponentUtils.getReturnValues(apiResult),
|
|
53
65
|
executePort: result.successPort,
|
|
@@ -81,6 +81,18 @@ export default class ApiPost extends ComponentCode {
|
|
|
81
81
|
|
|
82
82
|
logger.debug("API Post Component is done.", workflowLogAttributes);
|
|
83
83
|
|
|
84
|
+
/*
|
|
85
|
+
* On the server API resolves with an HTTPErrorResponse instead of
|
|
86
|
+
* throwing, so the catch below never sees an HTTP error - a 4xx/5xx used
|
|
87
|
+
* to take the success port.
|
|
88
|
+
*/
|
|
89
|
+
if (apiResult instanceof HTTPErrorResponse) {
|
|
90
|
+
return Promise.resolve({
|
|
91
|
+
returnValues: ApiComponentUtils.getReturnValues(apiResult),
|
|
92
|
+
executePort: result.errorPort,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
|
|
84
96
|
return Promise.resolve({
|
|
85
97
|
returnValues: ApiComponentUtils.getReturnValues(apiResult),
|
|
86
98
|
executePort: result.successPort,
|