@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
|
@@ -32,6 +32,9 @@ import {
|
|
|
32
32
|
import URL from "../../Types/API/URL";
|
|
33
33
|
import DatabaseConfig from "../DatabaseConfig";
|
|
34
34
|
import AlertSeverityService from "./AlertSeverityService";
|
|
35
|
+
import ProjectScopedReferenceValidator, {
|
|
36
|
+
resolveReferenceId,
|
|
37
|
+
} from "../Utils/Database/ProjectScopedReferenceValidator";
|
|
35
38
|
import AlertEpisodeMemberService from "./AlertEpisodeMemberService";
|
|
36
39
|
import AlertEpisodeOwnerUserService from "./AlertEpisodeOwnerUserService";
|
|
37
40
|
import AlertEpisodeOwnerTeamService from "./AlertEpisodeOwnerTeamService";
|
|
@@ -94,6 +97,36 @@ export class Service extends DatabaseService<Model> {
|
|
|
94
97
|
updateBy.query,
|
|
95
98
|
updateBy.props,
|
|
96
99
|
);
|
|
100
|
+
|
|
101
|
+
/*
|
|
102
|
+
* An episode carries the same project-scoped state and severity an alert
|
|
103
|
+
* does, on FKs that are equally ON DELETE NO ACTION, so an id from another
|
|
104
|
+
* project here leaves that project undeletable in exactly the same way.
|
|
105
|
+
* onBeforeCreate overwrites currentAlertStateId with this project's
|
|
106
|
+
* created state, which leaves the severity as the only create-reachable
|
|
107
|
+
* column — but an update can write either.
|
|
108
|
+
*/
|
|
109
|
+
await ProjectScopedReferenceValidator.validateReferencesBelongToProject({
|
|
110
|
+
projectId: updateBy.props.tenantId,
|
|
111
|
+
subject: "alert episode",
|
|
112
|
+
references: [
|
|
113
|
+
{
|
|
114
|
+
modelName: "Alert State",
|
|
115
|
+
id:
|
|
116
|
+
resolveReferenceId(updateBy.data.currentAlertStateId) ||
|
|
117
|
+
resolveReferenceId(updateBy.data.currentAlertState),
|
|
118
|
+
service: AlertStateService,
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
modelName: "Alert Severity",
|
|
122
|
+
id:
|
|
123
|
+
resolveReferenceId(updateBy.data.alertSeverityId) ||
|
|
124
|
+
resolveReferenceId(updateBy.data.alertSeverity),
|
|
125
|
+
service: AlertSeverityService,
|
|
126
|
+
},
|
|
127
|
+
],
|
|
128
|
+
});
|
|
129
|
+
|
|
97
130
|
return { updateBy, carryForward: null };
|
|
98
131
|
}
|
|
99
132
|
|
|
@@ -141,6 +174,20 @@ export class Service extends DatabaseService<Model> {
|
|
|
141
174
|
|
|
142
175
|
createBy.data.currentAlertStateId = alertState.id;
|
|
143
176
|
|
|
177
|
+
await ProjectScopedReferenceValidator.validateReferencesBelongToProject({
|
|
178
|
+
projectId: projectId,
|
|
179
|
+
subject: "alert episode",
|
|
180
|
+
references: [
|
|
181
|
+
{
|
|
182
|
+
modelName: "Alert Severity",
|
|
183
|
+
id:
|
|
184
|
+
resolveReferenceId(createBy.data.alertSeverityId) ||
|
|
185
|
+
resolveReferenceId(createBy.data.alertSeverity),
|
|
186
|
+
service: AlertSeverityService,
|
|
187
|
+
},
|
|
188
|
+
],
|
|
189
|
+
});
|
|
190
|
+
|
|
144
191
|
// Auto-generate episode number
|
|
145
192
|
const episodeCounterResult: {
|
|
146
193
|
counter: number;
|
|
@@ -29,6 +29,10 @@ import Model from "../../Models/DatabaseModels/Alert";
|
|
|
29
29
|
import AlertOwnerTeam from "../../Models/DatabaseModels/AlertOwnerTeam";
|
|
30
30
|
import AlertOwnerUser from "../../Models/DatabaseModels/AlertOwnerUser";
|
|
31
31
|
import AlertState from "../../Models/DatabaseModels/AlertState";
|
|
32
|
+
import MonitorStatusService from "./MonitorStatusService";
|
|
33
|
+
import ProjectScopedReferenceValidator, {
|
|
34
|
+
resolveReferenceId,
|
|
35
|
+
} from "../Utils/Database/ProjectScopedReferenceValidator";
|
|
32
36
|
import AlertStateTimeline from "../../Models/DatabaseModels/AlertStateTimeline";
|
|
33
37
|
import User from "../../Models/DatabaseModels/User";
|
|
34
38
|
import { IsBillingEnabled } from "../EnvironmentConfig";
|
|
@@ -258,9 +262,98 @@ export class Service extends DatabaseService<Model> {
|
|
|
258
262
|
updateBy.query,
|
|
259
263
|
updateBy.props,
|
|
260
264
|
);
|
|
265
|
+
|
|
266
|
+
await this.validateProjectScopedReferences(updateBy);
|
|
267
|
+
|
|
261
268
|
return { updateBy, carryForward: null };
|
|
262
269
|
}
|
|
263
270
|
|
|
271
|
+
/*
|
|
272
|
+
* An update can repoint an alert at another project's state, severity or
|
|
273
|
+
* monitor status just as easily as a create can, and the result is the same:
|
|
274
|
+
* the referenced project can no longer be deleted. Only the columns actually
|
|
275
|
+
* being written are checked, so ordinary updates cost no extra queries.
|
|
276
|
+
*/
|
|
277
|
+
private async validateProjectScopedReferences(
|
|
278
|
+
updateBy: UpdateBy<Model>,
|
|
279
|
+
): Promise<void> {
|
|
280
|
+
const alertStateId: ObjectID | string | undefined =
|
|
281
|
+
resolveReferenceId(updateBy.data.currentAlertStateId) ||
|
|
282
|
+
resolveReferenceId(updateBy.data.currentAlertState);
|
|
283
|
+
|
|
284
|
+
const alertSeverityId: ObjectID | string | undefined =
|
|
285
|
+
resolveReferenceId(updateBy.data.alertSeverityId) ||
|
|
286
|
+
resolveReferenceId(updateBy.data.alertSeverity);
|
|
287
|
+
|
|
288
|
+
const monitorStatusId: ObjectID | string | undefined =
|
|
289
|
+
resolveReferenceId(
|
|
290
|
+
updateBy.data.monitorStatusWhenThisAlertWasCreatedId,
|
|
291
|
+
) ||
|
|
292
|
+
resolveReferenceId(updateBy.data.monitorStatusWhenThisAlertWasCreated);
|
|
293
|
+
|
|
294
|
+
if (!alertStateId && !alertSeverityId && !monitorStatusId) {
|
|
295
|
+
return;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/*
|
|
299
|
+
* Root/API updates do not always carry a tenantId, so fall back to the
|
|
300
|
+
* project of each alert the query actually matches.
|
|
301
|
+
*/
|
|
302
|
+
const projectIds: Array<ObjectID> = updateBy.props.tenantId
|
|
303
|
+
? [updateBy.props.tenantId]
|
|
304
|
+
: await this.getProjectIdsForUpdateQuery(updateBy);
|
|
305
|
+
|
|
306
|
+
for (const projectId of projectIds) {
|
|
307
|
+
await ProjectScopedReferenceValidator.validateReferencesBelongToProject({
|
|
308
|
+
projectId: projectId,
|
|
309
|
+
subject: "alert",
|
|
310
|
+
references: [
|
|
311
|
+
{
|
|
312
|
+
modelName: "Alert State",
|
|
313
|
+
id: alertStateId,
|
|
314
|
+
service: AlertStateService,
|
|
315
|
+
},
|
|
316
|
+
{
|
|
317
|
+
modelName: "Alert Severity",
|
|
318
|
+
id: alertSeverityId,
|
|
319
|
+
service: AlertSeverityService,
|
|
320
|
+
},
|
|
321
|
+
{
|
|
322
|
+
modelName: "Monitor Status",
|
|
323
|
+
id: monitorStatusId,
|
|
324
|
+
service: MonitorStatusService,
|
|
325
|
+
},
|
|
326
|
+
],
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
private async getProjectIdsForUpdateQuery(
|
|
332
|
+
updateBy: UpdateBy<Model>,
|
|
333
|
+
): Promise<Array<ObjectID>> {
|
|
334
|
+
const alerts: Array<Model> = await this.findBy({
|
|
335
|
+
query: updateBy.query,
|
|
336
|
+
select: {
|
|
337
|
+
projectId: true,
|
|
338
|
+
},
|
|
339
|
+
limit: LIMIT_MAX,
|
|
340
|
+
skip: 0,
|
|
341
|
+
props: {
|
|
342
|
+
isRoot: true,
|
|
343
|
+
},
|
|
344
|
+
});
|
|
345
|
+
|
|
346
|
+
const projectIds: Dictionary<ObjectID> = {};
|
|
347
|
+
|
|
348
|
+
for (const alert of alerts) {
|
|
349
|
+
if (alert.projectId) {
|
|
350
|
+
projectIds[alert.projectId.toString()] = alert.projectId;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
return Object.values(projectIds);
|
|
355
|
+
}
|
|
356
|
+
|
|
264
357
|
@CaptureSpan()
|
|
265
358
|
protected override async onBeforeCreate(
|
|
266
359
|
createBy: CreateBy<Model>,
|
|
@@ -293,6 +386,38 @@ export class Service extends DatabaseService<Model> {
|
|
|
293
386
|
|
|
294
387
|
createBy.data.currentAlertStateId = alertState.id;
|
|
295
388
|
|
|
389
|
+
/*
|
|
390
|
+
* The severity and the monitor status stamped on the alert come from the
|
|
391
|
+
* monitor criteria or the API caller, neither of which checked that the
|
|
392
|
+
* record belongs to this project. Persisting another project's id leaves
|
|
393
|
+
* that project undeletable. Runs before the counter increment so a
|
|
394
|
+
* rejected create does not burn an alert number.
|
|
395
|
+
*/
|
|
396
|
+
await ProjectScopedReferenceValidator.validateReferencesBelongToProject({
|
|
397
|
+
projectId: projectId,
|
|
398
|
+
subject: "alert",
|
|
399
|
+
references: [
|
|
400
|
+
{
|
|
401
|
+
modelName: "Alert Severity",
|
|
402
|
+
id:
|
|
403
|
+
resolveReferenceId(createBy.data.alertSeverityId) ||
|
|
404
|
+
resolveReferenceId(createBy.data.alertSeverity),
|
|
405
|
+
service: AlertSeverityService,
|
|
406
|
+
},
|
|
407
|
+
{
|
|
408
|
+
modelName: "Monitor Status",
|
|
409
|
+
id:
|
|
410
|
+
resolveReferenceId(
|
|
411
|
+
createBy.data.monitorStatusWhenThisAlertWasCreatedId,
|
|
412
|
+
) ||
|
|
413
|
+
resolveReferenceId(
|
|
414
|
+
createBy.data.monitorStatusWhenThisAlertWasCreated,
|
|
415
|
+
),
|
|
416
|
+
service: MonitorStatusService,
|
|
417
|
+
},
|
|
418
|
+
],
|
|
419
|
+
});
|
|
420
|
+
|
|
296
421
|
const alertCounterResult: {
|
|
297
422
|
counter: number;
|
|
298
423
|
prefix: string | undefined;
|
|
@@ -37,6 +37,13 @@ export interface PaymentMethod {
|
|
|
37
37
|
isDefault: boolean;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
/*
|
|
41
|
+
* Stripe rejects a trial_end more than two years past the billing cycle
|
|
42
|
+
* anchor. Enforce the same ceiling here so an admin gets a readable error
|
|
43
|
+
* instead of a raw payment-provider failure.
|
|
44
|
+
*/
|
|
45
|
+
export const MAX_TRIAL_LENGTH_IN_DAYS: number = 730;
|
|
46
|
+
|
|
40
47
|
export interface Invoice {
|
|
41
48
|
id: string;
|
|
42
49
|
amount: number;
|
|
@@ -870,6 +877,97 @@ export class BillingService extends BaseService {
|
|
|
870
877
|
}
|
|
871
878
|
}
|
|
872
879
|
|
|
880
|
+
/*
|
|
881
|
+
* Moves the trial end of a project's subscriptions to a new date.
|
|
882
|
+
*
|
|
883
|
+
* Both the flat-fee subscription and the metered subscription have to move
|
|
884
|
+
* together: they were created with the same trial_end (see subscribeToPlan),
|
|
885
|
+
* and leaving the metered one behind would start billing usage while the
|
|
886
|
+
* customer still believes they are on trial.
|
|
887
|
+
*/
|
|
888
|
+
@CaptureSpan()
|
|
889
|
+
public async extendTrial(data: {
|
|
890
|
+
subscriptionId: string;
|
|
891
|
+
meteredSubscriptionId?: string | undefined;
|
|
892
|
+
trialEndsAt: Date;
|
|
893
|
+
}): Promise<void> {
|
|
894
|
+
if (!this.isBillingEnabled()) {
|
|
895
|
+
throw new BadDataException(Errors.BillingService.BILLING_NOT_ENABLED);
|
|
896
|
+
}
|
|
897
|
+
|
|
898
|
+
if (!OneUptimeDate.isInTheFuture(data.trialEndsAt)) {
|
|
899
|
+
throw new BadDataException(Errors.BillingService.TRIAL_END_DATE_IN_PAST);
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
if (
|
|
903
|
+
OneUptimeDate.isAfter(
|
|
904
|
+
data.trialEndsAt,
|
|
905
|
+
OneUptimeDate.getSomeDaysAfter(MAX_TRIAL_LENGTH_IN_DAYS),
|
|
906
|
+
)
|
|
907
|
+
) {
|
|
908
|
+
throw new BadDataException(
|
|
909
|
+
Errors.BillingService.TRIAL_END_DATE_TOO_FAR_IN_FUTURE,
|
|
910
|
+
);
|
|
911
|
+
}
|
|
912
|
+
|
|
913
|
+
const subscriptionIds: Array<string> = [data.subscriptionId];
|
|
914
|
+
|
|
915
|
+
if (data.meteredSubscriptionId) {
|
|
916
|
+
subscriptionIds.push(data.meteredSubscriptionId);
|
|
917
|
+
}
|
|
918
|
+
|
|
919
|
+
/*
|
|
920
|
+
* Validate every subscription before touching any of them. Updating the
|
|
921
|
+
* flat-fee subscription and then discovering the metered one is cancelled
|
|
922
|
+
* would leave the project's two subscriptions on different trial dates.
|
|
923
|
+
*/
|
|
924
|
+
for (const subscriptionId of subscriptionIds) {
|
|
925
|
+
const subscription: Stripe.Subscription =
|
|
926
|
+
await this.getSubscription(subscriptionId);
|
|
927
|
+
|
|
928
|
+
if (!subscription) {
|
|
929
|
+
throw new BadDataException(
|
|
930
|
+
Errors.BillingService.SUBSCRIPTION_NOT_FOUND,
|
|
931
|
+
);
|
|
932
|
+
}
|
|
933
|
+
|
|
934
|
+
if (
|
|
935
|
+
subscription.status === "canceled" ||
|
|
936
|
+
subscription.status === "incomplete_expired"
|
|
937
|
+
) {
|
|
938
|
+
throw new BadDataException(
|
|
939
|
+
Errors.BillingService.CANNOT_EXTEND_TRIAL_ON_CANCELLED_SUBSCRIPTION,
|
|
940
|
+
);
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
|
|
944
|
+
for (const subscriptionId of subscriptionIds) {
|
|
945
|
+
await this.stripe.subscriptions.update(subscriptionId, {
|
|
946
|
+
trial_end: OneUptimeDate.toUnixTimestamp(data.trialEndsAt),
|
|
947
|
+
|
|
948
|
+
/*
|
|
949
|
+
* Setting trial_end also moves the billing cycle anchor to that date.
|
|
950
|
+
* With the default proration behaviour Stripe raises proration line
|
|
951
|
+
* items for the shifted period, which is exactly the surprise invoice
|
|
952
|
+
* extending a trial is meant to prevent - so prorations are disabled.
|
|
953
|
+
*
|
|
954
|
+
* Caveat: this only silences the flat-fee subscription. Usage-based
|
|
955
|
+
* billing is not subject to proration, so closing the metered
|
|
956
|
+
* subscription's period early still invoices the usage recorded in it.
|
|
957
|
+
* For a project that is still trialing that is nothing (trial usage is
|
|
958
|
+
* not billable), but extending the trial of an already-active project
|
|
959
|
+
* bills its accrued usage immediately - the admin page warns about
|
|
960
|
+
* this before the extension is submitted.
|
|
961
|
+
*/
|
|
962
|
+
proration_behavior: "none",
|
|
963
|
+
});
|
|
964
|
+
|
|
965
|
+
logger.debug(
|
|
966
|
+
`Extended trial for subscription ${subscriptionId} to ${data.trialEndsAt.toISOString()}`,
|
|
967
|
+
);
|
|
968
|
+
}
|
|
969
|
+
}
|
|
970
|
+
|
|
873
971
|
@CaptureSpan()
|
|
874
972
|
public async getSubscriptionStatus(
|
|
875
973
|
subscriptionId: string,
|
|
@@ -1552,21 +1552,10 @@ class DatabaseService<TBaseModel extends BaseModel> extends BaseService {
|
|
|
1552
1552
|
try {
|
|
1553
1553
|
this.setTelemetryContextFromProps(findBy.props);
|
|
1554
1554
|
|
|
1555
|
-
let automaticallyAddedCreatedAtInSelect: boolean = false;
|
|
1556
|
-
|
|
1557
1555
|
if (!findBy.sort || Object.keys(findBy.sort).length === 0) {
|
|
1558
1556
|
findBy.sort = {
|
|
1559
1557
|
createdAt: SortOrder.Descending,
|
|
1560
1558
|
};
|
|
1561
|
-
|
|
1562
|
-
if (!findBy.select) {
|
|
1563
|
-
findBy.select = {} as any;
|
|
1564
|
-
}
|
|
1565
|
-
|
|
1566
|
-
if (!(findBy.select as any)["createdAt"]) {
|
|
1567
|
-
(findBy.select as any)["createdAt"] = true;
|
|
1568
|
-
automaticallyAddedCreatedAtInSelect = true;
|
|
1569
|
-
}
|
|
1570
1559
|
}
|
|
1571
1560
|
|
|
1572
1561
|
const onFind: OnFind<TBaseModel> = findBy.props.ignoreHooks
|
|
@@ -1600,6 +1589,9 @@ class DatabaseService<TBaseModel extends BaseModel> extends BaseService {
|
|
|
1600
1589
|
onBeforeFind.query = result.query;
|
|
1601
1590
|
onBeforeFind.select = result.select || undefined;
|
|
1602
1591
|
|
|
1592
|
+
const sortColumnsAddedToSelect: Array<string> =
|
|
1593
|
+
this.addSortColumnsToSelect(onBeforeFind);
|
|
1594
|
+
|
|
1603
1595
|
if (!(onBeforeFind.skip instanceof PositiveNumber)) {
|
|
1604
1596
|
onBeforeFind.skip = new PositiveNumber(onBeforeFind.skip);
|
|
1605
1597
|
}
|
|
@@ -1634,8 +1626,8 @@ class DatabaseService<TBaseModel extends BaseModel> extends BaseService {
|
|
|
1634
1626
|
decryptedItems = this.sanitizeFindByItems(decryptedItems, onBeforeFind);
|
|
1635
1627
|
|
|
1636
1628
|
for (const item of decryptedItems) {
|
|
1637
|
-
|
|
1638
|
-
delete (item as any)
|
|
1629
|
+
for (const sortColumn of sortColumnsAddedToSelect) {
|
|
1630
|
+
delete (item as any)[sortColumn];
|
|
1639
1631
|
}
|
|
1640
1632
|
}
|
|
1641
1633
|
|
|
@@ -1652,6 +1644,67 @@ class DatabaseService<TBaseModel extends BaseModel> extends BaseService {
|
|
|
1652
1644
|
}
|
|
1653
1645
|
}
|
|
1654
1646
|
|
|
1647
|
+
/**
|
|
1648
|
+
* Adds every sorted column to the select, and returns the ones it added so
|
|
1649
|
+
* `_findBy` can strip them back off the results.
|
|
1650
|
+
*
|
|
1651
|
+
* A column can be ordered by without being selected in a plain SELECT, but
|
|
1652
|
+
* not once a relation is also selected: the join sends the query down
|
|
1653
|
+
* TypeORM's paginated path, which wraps it and orders the outer SELECT by a
|
|
1654
|
+
* column the inner query only emits when that column was selected. The
|
|
1655
|
+
* request then fails outright with `column distinctAlias.<Alias>_<column>
|
|
1656
|
+
* does not exist`. Callers should not have to know that, so close the gap
|
|
1657
|
+
* here for every sort rather than leaving each call site to remember.
|
|
1658
|
+
*
|
|
1659
|
+
* Deliberately runs *after* the read-permission check. ORDER BY is not
|
|
1660
|
+
* permission-checked, so a column being sorted on is already reaching the
|
|
1661
|
+
* database - adding it to the select must not be able to turn a query that
|
|
1662
|
+
* worked into a permission error. The values never reach the caller.
|
|
1663
|
+
*/
|
|
1664
|
+
private addSortColumnsToSelect(findBy: FindBy<TBaseModel>): Array<string> {
|
|
1665
|
+
/*
|
|
1666
|
+
* No select at all means every column is selected, so there is nothing to
|
|
1667
|
+
* fill in.
|
|
1668
|
+
*/
|
|
1669
|
+
if (!findBy.select) {
|
|
1670
|
+
return [];
|
|
1671
|
+
}
|
|
1672
|
+
|
|
1673
|
+
const sortColumnsToAdd: Array<string> = Object.keys(
|
|
1674
|
+
findBy.sort || {},
|
|
1675
|
+
).filter((sortColumn: string) => {
|
|
1676
|
+
if ((findBy.select as any)[sortColumn] !== undefined) {
|
|
1677
|
+
return false;
|
|
1678
|
+
}
|
|
1679
|
+
|
|
1680
|
+
/*
|
|
1681
|
+
* Sorting by a relation orders through the joined table, which has its
|
|
1682
|
+
* own alias - adding the relation to the select here would instead turn
|
|
1683
|
+
* it into a fetched relation.
|
|
1684
|
+
*/
|
|
1685
|
+
return (
|
|
1686
|
+
this.model.hasColumn(sortColumn) &&
|
|
1687
|
+
!this.model.isEntityColumn(sortColumn)
|
|
1688
|
+
);
|
|
1689
|
+
});
|
|
1690
|
+
|
|
1691
|
+
if (sortColumnsToAdd.length === 0) {
|
|
1692
|
+
return [];
|
|
1693
|
+
}
|
|
1694
|
+
|
|
1695
|
+
/*
|
|
1696
|
+
* Copied rather than mutated: sanitizeSelect hands back the caller's own
|
|
1697
|
+
* select object, and callers reuse those across queries.
|
|
1698
|
+
*/
|
|
1699
|
+
findBy.select = { ...(findBy.select as any) };
|
|
1700
|
+
|
|
1701
|
+
for (const sortColumn of sortColumnsToAdd) {
|
|
1702
|
+
(findBy.select as any)[sortColumn] = true;
|
|
1703
|
+
}
|
|
1704
|
+
|
|
1705
|
+
return sortColumnsToAdd;
|
|
1706
|
+
}
|
|
1707
|
+
|
|
1655
1708
|
private sanitizeFindByItems(
|
|
1656
1709
|
items: Array<TBaseModel>,
|
|
1657
1710
|
findBy: FindBy<TBaseModel>,
|
|
@@ -1841,6 +1894,14 @@ class DatabaseService<TBaseModel extends BaseModel> extends BaseService {
|
|
|
1841
1894
|
|
|
1842
1895
|
const dataColumns: [string, boolean][] = [];
|
|
1843
1896
|
const dataKeys: string[] = Object.keys(data);
|
|
1897
|
+
|
|
1898
|
+
/*
|
|
1899
|
+
* An update that carries no columns writes nothing, yet it would still
|
|
1900
|
+
* match rows - so returning the matched count reported a write that
|
|
1901
|
+
* never happened. Treat it like a query that matched nothing instead.
|
|
1902
|
+
*/
|
|
1903
|
+
const hasColumnsToUpdate: boolean = dataKeys.length > 0;
|
|
1904
|
+
|
|
1844
1905
|
for (const key of dataKeys) {
|
|
1845
1906
|
dataColumns.push([key, true]);
|
|
1846
1907
|
}
|
|
@@ -1879,13 +1940,15 @@ class DatabaseService<TBaseModel extends BaseModel> extends BaseService {
|
|
|
1879
1940
|
}
|
|
1880
1941
|
}
|
|
1881
1942
|
|
|
1882
|
-
const items: Array<TBaseModel> =
|
|
1883
|
-
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1943
|
+
const items: Array<TBaseModel> = hasColumnsToUpdate
|
|
1944
|
+
? await this._findBy({
|
|
1945
|
+
query: beforeUpdateBy.query,
|
|
1946
|
+
skip: updateBy.skip.toNumber(),
|
|
1947
|
+
limit: updateBy.limit.toNumber(),
|
|
1948
|
+
select: selectColumns,
|
|
1949
|
+
props: { isRoot: true, ignoreHooks: true },
|
|
1950
|
+
})
|
|
1951
|
+
: [];
|
|
1889
1952
|
|
|
1890
1953
|
for (const item of items) {
|
|
1891
1954
|
/*
|
|
@@ -2176,6 +2239,107 @@ class DatabaseService<TBaseModel extends BaseModel> extends BaseService {
|
|
|
2176
2239
|
await repository.manager.query(sql, params);
|
|
2177
2240
|
}
|
|
2178
2241
|
|
|
2242
|
+
/*
|
|
2243
|
+
* Atomically add to numeric columns and set literal columns for one row,
|
|
2244
|
+
* in a SINGLE auto-committed UPDATE, with no hooks and no `version` bump.
|
|
2245
|
+
*
|
|
2246
|
+
* This is the counter-flush primitive. `updateColumnsByIdWithoutHooks`
|
|
2247
|
+
* can't express it (a read-modify-write would lose concurrent writers'
|
|
2248
|
+
* increments, and the value isn't known to the caller), and
|
|
2249
|
+
* `getRepository().increment()` can't either: it goes through
|
|
2250
|
+
* UpdateQueryBuilder, which always appends `version = version + 1`, so an
|
|
2251
|
+
* ingest-driven counter bump would fight the optimistic lock on a row a
|
|
2252
|
+
* human may be editing — and it can't set a second column in the same
|
|
2253
|
+
* statement.
|
|
2254
|
+
*
|
|
2255
|
+
* `COALESCE(col, 0)` so a NULL counter starts from zero rather than
|
|
2256
|
+
* staying NULL forever.
|
|
2257
|
+
*
|
|
2258
|
+
* Column and table identifiers come from entity metadata (never from the
|
|
2259
|
+
* caller) and every value is bound as a parameter, so this is not an
|
|
2260
|
+
* injection surface. Use ONLY for trusted, internal, side-effect-free
|
|
2261
|
+
* column writes.
|
|
2262
|
+
*/
|
|
2263
|
+
@CaptureSpan()
|
|
2264
|
+
public async atomicAddToColumnsByIdWithoutHooks(input: {
|
|
2265
|
+
id: ObjectID;
|
|
2266
|
+
add: Partial<Record<keyof TBaseModel, number>>;
|
|
2267
|
+
set?: PartialEntity<TBaseModel> | undefined;
|
|
2268
|
+
}): Promise<void> {
|
|
2269
|
+
if (!input.id) {
|
|
2270
|
+
throw new BadDataException("id is required");
|
|
2271
|
+
}
|
|
2272
|
+
|
|
2273
|
+
const repository: Repository<TBaseModel> = this.getRepository();
|
|
2274
|
+
const metadata: EntityMetadata = repository.metadata;
|
|
2275
|
+
const driver: Driver = repository.manager.connection.driver;
|
|
2276
|
+
|
|
2277
|
+
const setClauses: Array<string> = [];
|
|
2278
|
+
const params: Array<unknown> = [];
|
|
2279
|
+
|
|
2280
|
+
const columnFor: (propertyName: string) => ColumnMetadata = (
|
|
2281
|
+
propertyName: string,
|
|
2282
|
+
): ColumnMetadata => {
|
|
2283
|
+
const column: ColumnMetadata | undefined =
|
|
2284
|
+
metadata.findColumnWithPropertyName(propertyName);
|
|
2285
|
+
if (!column) {
|
|
2286
|
+
throw new BadDataException(
|
|
2287
|
+
`atomicAddToColumnsByIdWithoutHooks: unknown column "${propertyName}" on "${metadata.tableName}"`,
|
|
2288
|
+
);
|
|
2289
|
+
}
|
|
2290
|
+
return column;
|
|
2291
|
+
};
|
|
2292
|
+
|
|
2293
|
+
for (const [propertyName, delta] of Object.entries(
|
|
2294
|
+
input.add as ObjectLiteral,
|
|
2295
|
+
)) {
|
|
2296
|
+
if (typeof delta !== "number" || !Number.isFinite(delta)) {
|
|
2297
|
+
throw new BadDataException(
|
|
2298
|
+
`atomicAddToColumnsByIdWithoutHooks: "${propertyName}" delta must be a finite number`,
|
|
2299
|
+
);
|
|
2300
|
+
}
|
|
2301
|
+
|
|
2302
|
+
const column: ColumnMetadata = columnFor(propertyName);
|
|
2303
|
+
params.push(delta);
|
|
2304
|
+
const quoted: string = `"${column.databaseName}"`;
|
|
2305
|
+
setClauses.push(`${quoted} = COALESCE(${quoted}, 0) + $${params.length}`);
|
|
2306
|
+
}
|
|
2307
|
+
|
|
2308
|
+
for (const [propertyName, value] of Object.entries(
|
|
2309
|
+
(input.set || {}) as ObjectLiteral,
|
|
2310
|
+
)) {
|
|
2311
|
+
if (typeof value === "function") {
|
|
2312
|
+
throw new BadDataException(
|
|
2313
|
+
`atomicAddToColumnsByIdWithoutHooks: SQL-expression values are not supported (column "${propertyName}"); pass a literal value.`,
|
|
2314
|
+
);
|
|
2315
|
+
}
|
|
2316
|
+
|
|
2317
|
+
const column: ColumnMetadata = columnFor(propertyName);
|
|
2318
|
+
params.push(driver.preparePersistentValue(value, column));
|
|
2319
|
+
setClauses.push(`"${column.databaseName}" = $${params.length}`);
|
|
2320
|
+
}
|
|
2321
|
+
|
|
2322
|
+
if (setClauses.length === 0) {
|
|
2323
|
+
return;
|
|
2324
|
+
}
|
|
2325
|
+
|
|
2326
|
+
if (metadata.updateDateColumn) {
|
|
2327
|
+
setClauses.push(
|
|
2328
|
+
`"${metadata.updateDateColumn.databaseName}" = CURRENT_TIMESTAMP`,
|
|
2329
|
+
);
|
|
2330
|
+
}
|
|
2331
|
+
|
|
2332
|
+
const primaryColumnName: string =
|
|
2333
|
+
metadata.primaryColumns[0]?.databaseName || "_id";
|
|
2334
|
+
params.push(input.id.toString());
|
|
2335
|
+
|
|
2336
|
+
const sql: string = `UPDATE "${metadata.tableName}" SET ${setClauses.join(
|
|
2337
|
+
", ",
|
|
2338
|
+
)} WHERE "${primaryColumnName}" = $${params.length}`;
|
|
2339
|
+
|
|
2340
|
+
await repository.manager.query(sql, params);
|
|
2341
|
+
}
|
|
2342
|
+
|
|
2179
2343
|
@CaptureSpan()
|
|
2180
2344
|
protected async atomicIncrementColumnValueByOne(data: {
|
|
2181
2345
|
id: ObjectID;
|
|
@@ -27,6 +27,9 @@ import { Red500, Yellow500, Purple500 } from "../../Types/BrandColors";
|
|
|
27
27
|
import URL from "../../Types/API/URL";
|
|
28
28
|
import DatabaseConfig from "../DatabaseConfig";
|
|
29
29
|
import IncidentSeverityService from "./IncidentSeverityService";
|
|
30
|
+
import ProjectScopedReferenceValidator, {
|
|
31
|
+
resolveReferenceId,
|
|
32
|
+
} from "../Utils/Database/ProjectScopedReferenceValidator";
|
|
30
33
|
import IncidentEpisodeMemberService from "./IncidentEpisodeMemberService";
|
|
31
34
|
import IncidentEpisodeOwnerUserService from "./IncidentEpisodeOwnerUserService";
|
|
32
35
|
import IncidentEpisodeOwnerTeamService from "./IncidentEpisodeOwnerTeamService";
|
|
@@ -90,6 +93,36 @@ export class Service extends DatabaseService<Model> {
|
|
|
90
93
|
updateBy.query,
|
|
91
94
|
updateBy.props,
|
|
92
95
|
);
|
|
96
|
+
|
|
97
|
+
/*
|
|
98
|
+
* An episode carries the same project-scoped state and severity an
|
|
99
|
+
* incident does, on FKs that are equally ON DELETE NO ACTION, so an id
|
|
100
|
+
* from another project here leaves that project undeletable in exactly
|
|
101
|
+
* the same way. onBeforeCreate overwrites currentIncidentStateId with
|
|
102
|
+
* this project's created state, which leaves the severity as the only
|
|
103
|
+
* create-reachable column — but an update can write either.
|
|
104
|
+
*/
|
|
105
|
+
await ProjectScopedReferenceValidator.validateReferencesBelongToProject({
|
|
106
|
+
projectId: updateBy.props.tenantId,
|
|
107
|
+
subject: "incident episode",
|
|
108
|
+
references: [
|
|
109
|
+
{
|
|
110
|
+
modelName: "Incident State",
|
|
111
|
+
id:
|
|
112
|
+
resolveReferenceId(updateBy.data.currentIncidentStateId) ||
|
|
113
|
+
resolveReferenceId(updateBy.data.currentIncidentState),
|
|
114
|
+
service: IncidentStateService,
|
|
115
|
+
},
|
|
116
|
+
{
|
|
117
|
+
modelName: "Incident Severity",
|
|
118
|
+
id:
|
|
119
|
+
resolveReferenceId(updateBy.data.incidentSeverityId) ||
|
|
120
|
+
resolveReferenceId(updateBy.data.incidentSeverity),
|
|
121
|
+
service: IncidentSeverityService,
|
|
122
|
+
},
|
|
123
|
+
],
|
|
124
|
+
});
|
|
125
|
+
|
|
93
126
|
return { updateBy, carryForward: null };
|
|
94
127
|
}
|
|
95
128
|
|
|
@@ -140,6 +173,20 @@ export class Service extends DatabaseService<Model> {
|
|
|
140
173
|
|
|
141
174
|
createBy.data.currentIncidentStateId = incidentState.id;
|
|
142
175
|
|
|
176
|
+
await ProjectScopedReferenceValidator.validateReferencesBelongToProject({
|
|
177
|
+
projectId: projectId,
|
|
178
|
+
subject: "incident episode",
|
|
179
|
+
references: [
|
|
180
|
+
{
|
|
181
|
+
modelName: "Incident Severity",
|
|
182
|
+
id:
|
|
183
|
+
resolveReferenceId(createBy.data.incidentSeverityId) ||
|
|
184
|
+
resolveReferenceId(createBy.data.incidentSeverity),
|
|
185
|
+
service: IncidentSeverityService,
|
|
186
|
+
},
|
|
187
|
+
],
|
|
188
|
+
});
|
|
189
|
+
|
|
143
190
|
// Auto-generate episode number
|
|
144
191
|
const episodeCounterResult: {
|
|
145
192
|
counter: number;
|