@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.
Files changed (414) hide show
  1. package/Models/AnalyticsModels/KubernetesCostAllocation.ts +103 -0
  2. package/Models/DatabaseModels/AlertEpisodeStateTimeline.ts +1 -0
  3. package/Models/DatabaseModels/AlertStateTimeline.ts +1 -0
  4. package/Models/DatabaseModels/IncidentEpisodeStateTimeline.ts +1 -0
  5. package/Models/DatabaseModels/IncidentStateTimeline.ts +1 -0
  6. package/Models/DatabaseModels/Index.ts +5 -0
  7. package/Models/DatabaseModels/LogDropFilter.ts +89 -0
  8. package/Models/DatabaseModels/NetworkDeviceDiscoveryScan.ts +13 -3
  9. package/Models/DatabaseModels/RecommendationDismissal.ts +463 -0
  10. package/Models/DatabaseModels/ScheduledMaintenanceStateTimeline.ts +1 -0
  11. package/Models/DatabaseModels/StatusPageGroup.ts +95 -0
  12. package/Models/DatabaseModels/TableView.ts +40 -0
  13. package/Models/DatabaseModels/TraceDropFilter.ts +89 -0
  14. package/Models/DatabaseModels/WorkflowVariable.ts +5 -1
  15. package/Server/API/AlertAPI.ts +32 -17
  16. package/Server/API/BaseAPI.ts +31 -2
  17. package/Server/API/BaseAnalyticsAPI.ts +36 -2
  18. package/Server/API/CommonAPI.ts +57 -0
  19. package/Server/API/IncidentAPI.ts +60 -33
  20. package/Server/API/IncidentEpisodeAPI.ts +31 -16
  21. package/Server/API/MonitorAPI.ts +30 -0
  22. package/Server/API/MonitorTemplateAPI.ts +8 -0
  23. package/Server/API/ProbeAPI.ts +196 -15
  24. package/Server/API/ProjectAPI.ts +79 -1
  25. package/Server/API/ScheduledMaintenanceAPI.ts +33 -18
  26. package/Server/API/StatusPageAPI.ts +74 -37
  27. package/Server/API/WorkspaceNotificationRuleAPI.ts +34 -4
  28. package/Server/Infrastructure/Postgres/SchemaMigrations/1785241000000-AddColumnsToTableView.ts +13 -0
  29. package/Server/Infrastructure/Postgres/SchemaMigrations/1785320000000-RepairCrossProjectIncidentReferences.ts +527 -0
  30. package/Server/Infrastructure/Postgres/SchemaMigrations/1785329453269-AddParentGroupToStatusPageGroup.ts +31 -0
  31. package/Server/Infrastructure/Postgres/SchemaMigrations/1785397674289-AddRecommendationDismissalTable.ts +55 -0
  32. package/Server/Infrastructure/Postgres/SchemaMigrations/1785405581596-AddDroppedCountersToDropFilters.ts +53 -0
  33. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +10 -0
  34. package/Server/Services/AlertEpisodeService.ts +47 -0
  35. package/Server/Services/AlertService.ts +125 -0
  36. package/Server/Services/BillingService.ts +98 -0
  37. package/Server/Services/DatabaseService.ts +184 -20
  38. package/Server/Services/IncidentEpisodeService.ts +47 -0
  39. package/Server/Services/IncidentService.ts +123 -0
  40. package/Server/Services/IncidentTemplateService.ts +123 -1
  41. package/Server/Services/Index.ts +2 -0
  42. package/Server/Services/LogDropFilterService.ts +133 -0
  43. package/Server/Services/MonitorProbeService.ts +94 -4
  44. package/Server/Services/MonitorService.ts +48 -43
  45. package/Server/Services/NetworkDeviceDiscoveryScanService.ts +70 -0
  46. package/Server/Services/ProbeService.ts +66 -0
  47. package/Server/Services/ProjectService.ts +131 -7
  48. package/Server/Services/RecommendationDismissalService.ts +52 -0
  49. package/Server/Services/RunbookAgentJobService.ts +68 -7
  50. package/Server/Services/ScheduledMaintenanceService.ts +103 -0
  51. package/Server/Services/ScheduledMaintenanceTemplateService.ts +90 -0
  52. package/Server/Services/StatusPageGroupService.ts +186 -0
  53. package/Server/Services/TraceDropFilterService.ts +133 -0
  54. package/Server/Types/Workflow/Components/API/Delete.ts +12 -0
  55. package/Server/Types/Workflow/Components/API/Get.ts +12 -0
  56. package/Server/Types/Workflow/Components/API/Patch.ts +12 -0
  57. package/Server/Types/Workflow/Components/API/Post.ts +12 -0
  58. package/Server/Types/Workflow/Components/API/Put.ts +13 -0
  59. package/Server/Utils/Database/ProjectScopedReferenceValidator.ts +212 -0
  60. package/Server/Utils/DropFilterValidation.ts +127 -0
  61. package/Server/Utils/Errors.ts +5 -0
  62. package/Server/Utils/Monitor/MonitorAlert.ts +28 -1
  63. package/Server/Utils/Monitor/MonitorIncident.ts +31 -2
  64. package/Server/Utils/Telemetry/AppMetrics.ts +31 -0
  65. package/Tests/Models/AnalyticsModels/KubernetesCostAllocation.test.ts +16 -0
  66. package/Tests/Models/DatabaseModels/MonitorProbeColumnAccessControl.test.ts +196 -0
  67. package/Tests/Models/RecommendationDismissalModel.test.ts +269 -0
  68. package/Tests/Server/API/BaseAPIUpdatePayloadValidation.test.ts +320 -0
  69. package/Tests/Server/API/BaseAnalyticsAPIUpdatePayloadValidation.test.ts +293 -0
  70. package/Tests/Server/API/CommonAPIAuthGuard.test.ts +164 -0
  71. package/Tests/Server/API/ProbeAPI.test.ts +422 -53
  72. package/Tests/Server/API/ProjectAPI.test.ts +180 -0
  73. package/Tests/Server/API/ProjectAPIExtendTrialBillingDisabled.test.ts +138 -0
  74. package/Tests/Server/API/ProjectScopedCustomRouteAuth.test.ts +458 -0
  75. package/Tests/Server/Infrastructure/ContainerBootConfiguration.test.ts +359 -0
  76. package/Tests/Server/Infrastructure/ProcessSignalDelivery.test.ts +427 -0
  77. package/Tests/Server/Services/BillingServiceExtendTrial.test.ts +439 -0
  78. package/Tests/Server/Services/CrossProjectReferenceWriteGuard.test.ts +810 -0
  79. package/Tests/Server/Services/DatabaseServiceAtomicAddToColumns.test.ts +269 -0
  80. package/Tests/Server/Services/DatabaseServiceEmptyUpdate.test.ts +277 -0
  81. package/Tests/Server/Services/DatabaseServiceSortColumnSelect.test.ts +201 -0
  82. package/Tests/Server/Services/DiscoveryScanClaimHookFreeSafety.test.ts +81 -23
  83. package/Tests/Server/Services/DropFilterSaveValidation.test.ts +398 -0
  84. package/Tests/Server/Services/MonitorProbeDeleteHooks.test.ts +280 -0
  85. package/Tests/Server/Services/MonitorProbeServiceProbeTenancy.test.ts +304 -0
  86. package/Tests/Server/Services/NetworkDeviceDiscoveryScanService.test.ts +262 -0
  87. package/Tests/Server/Services/ProjectServiceExtendTrial.test.ts +614 -0
  88. package/Tests/Server/Services/RecommendationDismissalService.test.ts +306 -0
  89. package/Tests/Server/Services/RepairCrossProjectIncidentReferencesMigration.test.ts +528 -0
  90. package/Tests/Server/Services/StatusPageGroupNesting.test.ts +395 -0
  91. package/Tests/Server/TestingUtils/Services/BillingServiceHelper.ts +26 -21
  92. package/Tests/Server/Types/Database/Permissions/WorkflowVariableColumnPermission.test.ts +227 -0
  93. package/Tests/Server/Types/Workflow/Components/ApiComponentErrorPort.test.ts +285 -0
  94. package/Tests/Server/Utils/Database/ProjectScopedReferenceValidator.test.ts +463 -0
  95. package/Tests/Server/Utils/DropFilterValidation.test.ts +269 -0
  96. package/Tests/Server/Utils/Telemetry/SpanUtil.test.ts +94 -0
  97. package/Tests/Types/DateUserTimezone.test.ts +52 -0
  98. package/Tests/Types/JSONFunctions.test.ts +103 -1
  99. package/Tests/Types/Monitor/KubernetesAlertTemplates.test.ts +177 -9
  100. package/Tests/Types/Monitor/MonitorStepDnsMonitor.test.ts +105 -0
  101. package/Tests/Types/Monitor/MonitorStepDnssecMonitor.test.ts +131 -0
  102. package/Tests/Types/Monitor/MonitorStepDomainMonitor.test.ts +60 -0
  103. package/Tests/Types/Monitor/MonitorStepExternalStatusPageMonitor.test.ts +82 -0
  104. package/Tests/Types/Monitor/MonitorStepInfrastructureMonitors.test.ts +268 -0
  105. package/Tests/Types/Monitor/MonitorStepMetricMonitor.test.ts +386 -0
  106. package/Tests/Types/Monitor/MonitorStepProfileMonitor.test.ts +185 -0
  107. package/Tests/Types/Monitor/MonitorStepSnmpMonitor.test.ts +156 -0
  108. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationCatalog.test.ts +371 -0
  109. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationCoverage.test.ts +901 -0
  110. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationNotificationMode.test.ts +607 -0
  111. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.test.ts +754 -0
  112. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationUtil.test.ts +960 -0
  113. package/Tests/Types/RollingTime/RollingTimeUtil.test.ts +186 -0
  114. package/Tests/Types/Runbook/RunbookStepTimeout.test.ts +410 -0
  115. package/Tests/Types/Telemetry/DropFilterSampling.test.ts +241 -0
  116. package/Tests/Types/Workspace/NotificationRuleConditionUtil.test.ts +353 -0
  117. package/Tests/Types/Workspace/NotificationRuleUtil.test.ts +566 -0
  118. package/Tests/UI/Components/CodeEditor.test.tsx +174 -0
  119. package/Tests/UI/Components/ErrorBoundary.test.tsx +555 -24
  120. package/Tests/UI/Components/InfoCard.test.tsx +358 -0
  121. package/Tests/UI/Components/LogTimeRangePicker.test.tsx +138 -0
  122. package/Tests/UI/Components/Modal.test.tsx +43 -5
  123. package/Tests/UI/Components/ModelTable/BaseModelTableColumnCustomization.test.tsx +679 -0
  124. package/Tests/UI/Components/ModelTable/BaseModelTableSearchLabels.test.tsx +397 -0
  125. package/Tests/UI/Components/ModelTable/ColumnCustomizationModal.test.tsx +999 -0
  126. package/Tests/UI/Components/ModelTable/ColumnPreference.test.ts +1678 -0
  127. package/Tests/UI/Components/ModelTable/CustomFieldColumns.test.tsx +1094 -0
  128. package/Tests/UI/Components/Runbook/StepTimeoutInput.test.tsx +386 -0
  129. package/Tests/UI/Components/StatusPage/ResourceGroupSection.test.tsx +671 -0
  130. package/Tests/UI/Components/TelemetryTimeRangePicker.test.tsx +404 -0
  131. package/Tests/UI/Utils/DropdownAlignment.test.ts +306 -0
  132. package/Tests/UI/Utils/TableFilterUrlState.test.ts +292 -0
  133. package/Tests/Utils/Monitor/MonitorSummaryProbeUtil.test.ts +263 -0
  134. package/Tests/Utils/NetworkDiscovery/ScanTargetUtil.test.ts +583 -0
  135. package/Tests/Utils/StatusPage/GroupNestingLayout.test.ts +1072 -0
  136. package/Tests/Utils/StatusPage/GroupTree.test.ts +583 -0
  137. package/Tests/Utils/StatusPage/ResourceUptime.test.ts +411 -0
  138. package/Tests/Utils/UserPreferences.test.ts +563 -0
  139. package/Types/Date.ts +15 -6
  140. package/Types/JSONFunctions.ts +7 -2
  141. package/Types/Kubernetes/KubernetesCostIngest.ts +37 -1
  142. package/Types/Monitor/KubernetesAlertTemplates.ts +205 -0
  143. package/Types/Monitor/MonitorStep.ts +10 -1
  144. package/Types/Monitor/MonitorStepMetricMonitor.ts +46 -1
  145. package/Types/Monitor/Recommendation/MonitorRecommendationCatalog.ts +413 -0
  146. package/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.ts +168 -0
  147. package/Types/Monitor/Recommendation/MonitorRecommendationTypes.ts +175 -0
  148. package/Types/Monitor/Recommendation/MonitorRecommendationUtil.ts +743 -0
  149. package/Types/Permission.ts +45 -0
  150. package/Types/Recommendation/RecommendationType.ts +20 -0
  151. package/Types/Runbook/RunbookExecutionDeadline.ts +129 -0
  152. package/Types/Runbook/RunbookStepTimeout.ts +202 -0
  153. package/Types/Telemetry/DropFilterSampling.ts +92 -0
  154. package/UI/Components/AI/GenerateFromAIModal.tsx +0 -2
  155. package/UI/Components/Accordion/Accordion.tsx +10 -2
  156. package/UI/Components/BulkUpdate/BulkLabelActions.tsx +0 -1
  157. package/UI/Components/CodeEditor/CodeEditor.tsx +34 -20
  158. package/UI/Components/Date/RangeStartAndEndDateView.tsx +0 -1
  159. package/UI/Components/EditionLabel/EditionLabel.tsx +1 -27
  160. package/UI/Components/Error/PageError.tsx +0 -4
  161. package/UI/Components/ErrorBoundary.tsx +252 -15
  162. package/UI/Components/InfoCard/InfoCard.tsx +58 -1
  163. package/UI/Components/LogsViewer/components/LogTimeRangePicker.tsx +34 -1
  164. package/UI/Components/MasterPage/MasterPage.tsx +65 -0
  165. package/UI/Components/Modal/Modal.tsx +16 -60
  166. package/UI/Components/ModelFormModal/ModelFormModal.tsx +0 -8
  167. package/UI/Components/ModelTable/BaseModelTable.tsx +503 -71
  168. package/UI/Components/ModelTable/Column.ts +17 -0
  169. package/UI/Components/ModelTable/ColumnCustomizationModal.tsx +523 -0
  170. package/UI/Components/ModelTable/ColumnPreference.ts +482 -0
  171. package/UI/Components/ModelTable/CustomFieldColumns.tsx +326 -0
  172. package/UI/Components/ModelTable/TableView.tsx +24 -2
  173. package/UI/Components/ModelTable/useCustomFieldColumns.ts +150 -0
  174. package/UI/Components/Runbook/StepTimeoutInput.tsx +173 -0
  175. package/UI/Components/SideMenu/SideMenu.tsx +24 -4
  176. package/UI/Components/StatusPage/ResourceGroupSection.tsx +231 -0
  177. package/UI/Components/Table/Table.tsx +14 -1
  178. package/UI/Components/Table/TableRow.tsx +180 -175
  179. package/UI/Components/Table/Types/Column.ts +2 -0
  180. package/UI/Components/TelemetryViewer/components/TelemetryTimeRangePicker.tsx +34 -1
  181. package/UI/Utils/DropdownAlignment.ts +162 -0
  182. package/UI/Utils/TableFilterUrlState.ts +59 -20
  183. package/Utils/API.ts +106 -2
  184. package/Utils/Monitor/MonitorSummaryProbeUtil.ts +130 -0
  185. package/Utils/NetworkDiscovery/ScanTargetUtil.ts +434 -0
  186. package/Utils/StatusPage/GroupNestingLayout.ts +343 -0
  187. package/Utils/StatusPage/GroupTree.ts +307 -0
  188. package/Utils/StatusPage/ResourceUptime.ts +90 -17
  189. package/Utils/UserPreferences.ts +53 -0
  190. package/build/dist/Models/AnalyticsModels/KubernetesCostAllocation.js +86 -0
  191. package/build/dist/Models/AnalyticsModels/KubernetesCostAllocation.js.map +1 -1
  192. package/build/dist/Models/DatabaseModels/AlertEpisodeStateTimeline.js +1 -0
  193. package/build/dist/Models/DatabaseModels/AlertEpisodeStateTimeline.js.map +1 -1
  194. package/build/dist/Models/DatabaseModels/AlertStateTimeline.js +1 -0
  195. package/build/dist/Models/DatabaseModels/AlertStateTimeline.js.map +1 -1
  196. package/build/dist/Models/DatabaseModels/IncidentEpisodeStateTimeline.js +1 -0
  197. package/build/dist/Models/DatabaseModels/IncidentEpisodeStateTimeline.js.map +1 -1
  198. package/build/dist/Models/DatabaseModels/IncidentStateTimeline.js +1 -0
  199. package/build/dist/Models/DatabaseModels/IncidentStateTimeline.js.map +1 -1
  200. package/build/dist/Models/DatabaseModels/Index.js +2 -0
  201. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  202. package/build/dist/Models/DatabaseModels/LogDropFilter.js +91 -0
  203. package/build/dist/Models/DatabaseModels/LogDropFilter.js.map +1 -1
  204. package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js +14 -4
  205. package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js.map +1 -1
  206. package/build/dist/Models/DatabaseModels/RecommendationDismissal.js +484 -0
  207. package/build/dist/Models/DatabaseModels/RecommendationDismissal.js.map +1 -0
  208. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceStateTimeline.js +1 -0
  209. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceStateTimeline.js.map +1 -1
  210. package/build/dist/Models/DatabaseModels/StatusPageGroup.js +94 -0
  211. package/build/dist/Models/DatabaseModels/StatusPageGroup.js.map +1 -1
  212. package/build/dist/Models/DatabaseModels/TableView.js +40 -0
  213. package/build/dist/Models/DatabaseModels/TableView.js.map +1 -1
  214. package/build/dist/Models/DatabaseModels/TraceDropFilter.js +91 -0
  215. package/build/dist/Models/DatabaseModels/TraceDropFilter.js.map +1 -1
  216. package/build/dist/Models/DatabaseModels/WorkflowVariable.js +5 -1
  217. package/build/dist/Models/DatabaseModels/WorkflowVariable.js.map +1 -1
  218. package/build/dist/Server/API/AlertAPI.js +22 -13
  219. package/build/dist/Server/API/AlertAPI.js.map +1 -1
  220. package/build/dist/Server/API/BaseAPI.js +22 -1
  221. package/build/dist/Server/API/BaseAPI.js.map +1 -1
  222. package/build/dist/Server/API/BaseAnalyticsAPI.js +24 -1
  223. package/build/dist/Server/API/BaseAnalyticsAPI.js.map +1 -1
  224. package/build/dist/Server/API/CommonAPI.js +42 -0
  225. package/build/dist/Server/API/CommonAPI.js.map +1 -1
  226. package/build/dist/Server/API/IncidentAPI.js +43 -26
  227. package/build/dist/Server/API/IncidentAPI.js.map +1 -1
  228. package/build/dist/Server/API/IncidentEpisodeAPI.js +21 -12
  229. package/build/dist/Server/API/IncidentEpisodeAPI.js.map +1 -1
  230. package/build/dist/Server/API/MonitorAPI.js +23 -0
  231. package/build/dist/Server/API/MonitorAPI.js.map +1 -1
  232. package/build/dist/Server/API/MonitorTemplateAPI.js +4 -0
  233. package/build/dist/Server/API/MonitorTemplateAPI.js.map +1 -1
  234. package/build/dist/Server/API/ProbeAPI.js +131 -15
  235. package/build/dist/Server/API/ProbeAPI.js.map +1 -1
  236. package/build/dist/Server/API/ProjectAPI.js +62 -3
  237. package/build/dist/Server/API/ProjectAPI.js.map +1 -1
  238. package/build/dist/Server/API/ScheduledMaintenanceAPI.js +23 -14
  239. package/build/dist/Server/API/ScheduledMaintenanceAPI.js.map +1 -1
  240. package/build/dist/Server/API/StatusPageAPI.js +61 -33
  241. package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
  242. package/build/dist/Server/API/WorkspaceNotificationRuleAPI.js +26 -2
  243. package/build/dist/Server/API/WorkspaceNotificationRuleAPI.js.map +1 -1
  244. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785241000000-AddColumnsToTableView.js +12 -0
  245. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785241000000-AddColumnsToTableView.js.map +1 -0
  246. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785320000000-RepairCrossProjectIncidentReferences.js +397 -0
  247. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785320000000-RepairCrossProjectIncidentReferences.js.map +1 -0
  248. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785329453269-AddParentGroupToStatusPageGroup.js +16 -0
  249. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785329453269-AddParentGroupToStatusPageGroup.js.map +1 -0
  250. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785397674289-AddRecommendationDismissalTable.js +30 -0
  251. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785397674289-AddRecommendationDismissalTable.js.map +1 -0
  252. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785405581596-AddDroppedCountersToDropFilters.js +34 -0
  253. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785405581596-AddDroppedCountersToDropFilters.js.map +1 -0
  254. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +10 -0
  255. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  256. package/build/dist/Server/Services/AlertEpisodeService.js +39 -0
  257. package/build/dist/Server/Services/AlertEpisodeService.js.map +1 -1
  258. package/build/dist/Server/Services/AlertService.js +95 -0
  259. package/build/dist/Server/Services/AlertService.js.map +1 -1
  260. package/build/dist/Server/Services/BillingService.js +71 -0
  261. package/build/dist/Server/Services/BillingService.js.map +1 -1
  262. package/build/dist/Server/Services/DatabaseService.js +140 -17
  263. package/build/dist/Server/Services/DatabaseService.js.map +1 -1
  264. package/build/dist/Server/Services/IncidentEpisodeService.js +39 -0
  265. package/build/dist/Server/Services/IncidentEpisodeService.js.map +1 -1
  266. package/build/dist/Server/Services/IncidentService.js +100 -0
  267. package/build/dist/Server/Services/IncidentService.js.map +1 -1
  268. package/build/dist/Server/Services/IncidentTemplateService.js +97 -0
  269. package/build/dist/Server/Services/IncidentTemplateService.js.map +1 -1
  270. package/build/dist/Server/Services/Index.js +2 -0
  271. package/build/dist/Server/Services/Index.js.map +1 -1
  272. package/build/dist/Server/Services/LogDropFilterService.js +93 -0
  273. package/build/dist/Server/Services/LogDropFilterService.js.map +1 -1
  274. package/build/dist/Server/Services/MonitorProbeService.js +73 -5
  275. package/build/dist/Server/Services/MonitorProbeService.js.map +1 -1
  276. package/build/dist/Server/Services/MonitorService.js +34 -39
  277. package/build/dist/Server/Services/MonitorService.js.map +1 -1
  278. package/build/dist/Server/Services/NetworkDeviceDiscoveryScanService.js +71 -0
  279. package/build/dist/Server/Services/NetworkDeviceDiscoveryScanService.js.map +1 -1
  280. package/build/dist/Server/Services/ProbeService.js +64 -0
  281. package/build/dist/Server/Services/ProbeService.js.map +1 -1
  282. package/build/dist/Server/Services/ProjectService.js +103 -7
  283. package/build/dist/Server/Services/ProjectService.js.map +1 -1
  284. package/build/dist/Server/Services/RecommendationDismissalService.js +50 -0
  285. package/build/dist/Server/Services/RecommendationDismissalService.js.map +1 -0
  286. package/build/dist/Server/Services/RunbookAgentJobService.js +63 -5
  287. package/build/dist/Server/Services/RunbookAgentJobService.js.map +1 -1
  288. package/build/dist/Server/Services/ScheduledMaintenanceService.js +83 -0
  289. package/build/dist/Server/Services/ScheduledMaintenanceService.js.map +1 -1
  290. package/build/dist/Server/Services/ScheduledMaintenanceTemplateService.js +65 -0
  291. package/build/dist/Server/Services/ScheduledMaintenanceTemplateService.js.map +1 -1
  292. package/build/dist/Server/Services/StatusPageGroupService.js +136 -0
  293. package/build/dist/Server/Services/StatusPageGroupService.js.map +1 -1
  294. package/build/dist/Server/Services/TraceDropFilterService.js +93 -0
  295. package/build/dist/Server/Services/TraceDropFilterService.js.map +1 -1
  296. package/build/dist/Server/Types/Workflow/Components/API/Delete.js +11 -0
  297. package/build/dist/Server/Types/Workflow/Components/API/Delete.js.map +1 -1
  298. package/build/dist/Server/Types/Workflow/Components/API/Get.js +11 -0
  299. package/build/dist/Server/Types/Workflow/Components/API/Get.js.map +1 -1
  300. package/build/dist/Server/Types/Workflow/Components/API/Patch.js +11 -0
  301. package/build/dist/Server/Types/Workflow/Components/API/Patch.js.map +1 -1
  302. package/build/dist/Server/Types/Workflow/Components/API/Post.js +11 -0
  303. package/build/dist/Server/Types/Workflow/Components/API/Post.js.map +1 -1
  304. package/build/dist/Server/Types/Workflow/Components/API/Put.js +12 -0
  305. package/build/dist/Server/Types/Workflow/Components/API/Put.js.map +1 -1
  306. package/build/dist/Server/Utils/Database/ProjectScopedReferenceValidator.js +132 -0
  307. package/build/dist/Server/Utils/Database/ProjectScopedReferenceValidator.js.map +1 -0
  308. package/build/dist/Server/Utils/DropFilterValidation.js +80 -0
  309. package/build/dist/Server/Utils/DropFilterValidation.js.map +1 -0
  310. package/build/dist/Server/Utils/Errors.js +3 -0
  311. package/build/dist/Server/Utils/Errors.js.map +1 -1
  312. package/build/dist/Server/Utils/Monitor/MonitorAlert.js +30 -12
  313. package/build/dist/Server/Utils/Monitor/MonitorAlert.js.map +1 -1
  314. package/build/dist/Server/Utils/Monitor/MonitorIncident.js +38 -18
  315. package/build/dist/Server/Utils/Monitor/MonitorIncident.js.map +1 -1
  316. package/build/dist/Server/Utils/Telemetry/AppMetrics.js +26 -0
  317. package/build/dist/Server/Utils/Telemetry/AppMetrics.js.map +1 -1
  318. package/build/dist/Types/Date.js +14 -4
  319. package/build/dist/Types/Date.js.map +1 -1
  320. package/build/dist/Types/JSONFunctions.js +8 -3
  321. package/build/dist/Types/JSONFunctions.js.map +1 -1
  322. package/build/dist/Types/Kubernetes/KubernetesCostIngest.js.map +1 -1
  323. package/build/dist/Types/Monitor/KubernetesAlertTemplates.js +192 -0
  324. package/build/dist/Types/Monitor/KubernetesAlertTemplates.js.map +1 -1
  325. package/build/dist/Types/Monitor/MonitorStep.js +6 -1
  326. package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
  327. package/build/dist/Types/Monitor/MonitorStepMetricMonitor.js +32 -1
  328. package/build/dist/Types/Monitor/MonitorStepMetricMonitor.js.map +1 -1
  329. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js +294 -0
  330. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js.map +1 -0
  331. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.js +110 -0
  332. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.js.map +1 -0
  333. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js +58 -0
  334. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js.map +1 -0
  335. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationUtil.js +451 -0
  336. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationUtil.js.map +1 -0
  337. package/build/dist/Types/Permission.js +40 -0
  338. package/build/dist/Types/Permission.js.map +1 -1
  339. package/build/dist/Types/Recommendation/RecommendationType.js +21 -0
  340. package/build/dist/Types/Recommendation/RecommendationType.js.map +1 -0
  341. package/build/dist/Types/Runbook/RunbookExecutionDeadline.js +93 -0
  342. package/build/dist/Types/Runbook/RunbookExecutionDeadline.js.map +1 -0
  343. package/build/dist/Types/Runbook/RunbookStepTimeout.js +142 -0
  344. package/build/dist/Types/Runbook/RunbookStepTimeout.js.map +1 -0
  345. package/build/dist/Types/Telemetry/DropFilterSampling.js +75 -0
  346. package/build/dist/Types/Telemetry/DropFilterSampling.js.map +1 -0
  347. package/build/dist/UI/Components/AI/GenerateFromAIModal.js +1 -2
  348. package/build/dist/UI/Components/AI/GenerateFromAIModal.js.map +1 -1
  349. package/build/dist/UI/Components/Accordion/Accordion.js +9 -2
  350. package/build/dist/UI/Components/Accordion/Accordion.js.map +1 -1
  351. package/build/dist/UI/Components/BulkUpdate/BulkLabelActions.js +1 -1
  352. package/build/dist/UI/Components/BulkUpdate/BulkLabelActions.js.map +1 -1
  353. package/build/dist/UI/Components/CodeEditor/CodeEditor.js +27 -14
  354. package/build/dist/UI/Components/CodeEditor/CodeEditor.js.map +1 -1
  355. package/build/dist/UI/Components/Date/RangeStartAndEndDateView.js +1 -1
  356. package/build/dist/UI/Components/Date/RangeStartAndEndDateView.js.map +1 -1
  357. package/build/dist/UI/Components/EditionLabel/EditionLabel.js +2 -20
  358. package/build/dist/UI/Components/EditionLabel/EditionLabel.js.map +1 -1
  359. package/build/dist/UI/Components/Error/PageError.js +1 -3
  360. package/build/dist/UI/Components/Error/PageError.js.map +1 -1
  361. package/build/dist/UI/Components/ErrorBoundary.js +145 -11
  362. package/build/dist/UI/Components/ErrorBoundary.js.map +1 -1
  363. package/build/dist/UI/Components/InfoCard/InfoCard.js +28 -1
  364. package/build/dist/UI/Components/InfoCard/InfoCard.js.map +1 -1
  365. package/build/dist/UI/Components/LogsViewer/components/LogTimeRangePicker.js +13 -2
  366. package/build/dist/UI/Components/LogsViewer/components/LogTimeRangePicker.js.map +1 -1
  367. package/build/dist/UI/Components/MasterPage/MasterPage.js +50 -1
  368. package/build/dist/UI/Components/MasterPage/MasterPage.js.map +1 -1
  369. package/build/dist/UI/Components/Modal/Modal.js +4 -32
  370. package/build/dist/UI/Components/Modal/Modal.js.map +1 -1
  371. package/build/dist/UI/Components/ModelFormModal/ModelFormModal.js.map +1 -1
  372. package/build/dist/UI/Components/ModelTable/BaseModelTable.js +308 -40
  373. package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
  374. package/build/dist/UI/Components/ModelTable/ColumnCustomizationModal.js +230 -0
  375. package/build/dist/UI/Components/ModelTable/ColumnCustomizationModal.js.map +1 -0
  376. package/build/dist/UI/Components/ModelTable/ColumnPreference.js +258 -0
  377. package/build/dist/UI/Components/ModelTable/ColumnPreference.js.map +1 -0
  378. package/build/dist/UI/Components/ModelTable/CustomFieldColumns.js +168 -0
  379. package/build/dist/UI/Components/ModelTable/CustomFieldColumns.js.map +1 -0
  380. package/build/dist/UI/Components/ModelTable/TableView.js +13 -2
  381. package/build/dist/UI/Components/ModelTable/TableView.js.map +1 -1
  382. package/build/dist/UI/Components/ModelTable/useCustomFieldColumns.js +84 -0
  383. package/build/dist/UI/Components/ModelTable/useCustomFieldColumns.js.map +1 -0
  384. package/build/dist/UI/Components/Runbook/StepTimeoutInput.js +101 -0
  385. package/build/dist/UI/Components/Runbook/StepTimeoutInput.js.map +1 -0
  386. package/build/dist/UI/Components/SideMenu/SideMenu.js +15 -5
  387. package/build/dist/UI/Components/SideMenu/SideMenu.js.map +1 -1
  388. package/build/dist/UI/Components/StatusPage/ResourceGroupSection.js +73 -0
  389. package/build/dist/UI/Components/StatusPage/ResourceGroupSection.js.map +1 -0
  390. package/build/dist/UI/Components/Table/Table.js +15 -2
  391. package/build/dist/UI/Components/Table/Table.js.map +1 -1
  392. package/build/dist/UI/Components/Table/TableRow.js +11 -6
  393. package/build/dist/UI/Components/Table/TableRow.js.map +1 -1
  394. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryTimeRangePicker.js +13 -2
  395. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryTimeRangePicker.js.map +1 -1
  396. package/build/dist/UI/Utils/DropdownAlignment.js +98 -0
  397. package/build/dist/UI/Utils/DropdownAlignment.js.map +1 -0
  398. package/build/dist/UI/Utils/TableFilterUrlState.js +48 -15
  399. package/build/dist/UI/Utils/TableFilterUrlState.js.map +1 -1
  400. package/build/dist/Utils/API.js +39 -2
  401. package/build/dist/Utils/API.js.map +1 -1
  402. package/build/dist/Utils/Monitor/MonitorSummaryProbeUtil.js +97 -0
  403. package/build/dist/Utils/Monitor/MonitorSummaryProbeUtil.js.map +1 -0
  404. package/build/dist/Utils/NetworkDiscovery/ScanTargetUtil.js +330 -0
  405. package/build/dist/Utils/NetworkDiscovery/ScanTargetUtil.js.map +1 -0
  406. package/build/dist/Utils/StatusPage/GroupNestingLayout.js +280 -0
  407. package/build/dist/Utils/StatusPage/GroupNestingLayout.js.map +1 -0
  408. package/build/dist/Utils/StatusPage/GroupTree.js +214 -0
  409. package/build/dist/Utils/StatusPage/GroupTree.js.map +1 -0
  410. package/build/dist/Utils/StatusPage/ResourceUptime.js +60 -16
  411. package/build/dist/Utils/StatusPage/ResourceUptime.js.map +1 -1
  412. package/build/dist/Utils/UserPreferences.js +33 -0
  413. package/build/dist/Utils/UserPreferences.js.map +1 -1
  414. package/package.json +1 -1
@@ -28,6 +28,9 @@ import ObjectID from "../../Types/ObjectID";
28
28
  import PositiveNumber from "../../Types/PositiveNumber";
29
29
  import Typeof from "../../Types/Typeof";
30
30
  import { applyIncidentSelfPrivacyFilter } from "../Utils/Incident/IncidentPrivacyFilter";
31
+ import ProjectScopedReferenceValidator, {
32
+ resolveReferenceId,
33
+ } from "../Utils/Database/ProjectScopedReferenceValidator";
31
34
  import UserNotificationEventType from "../../Types/UserNotification/UserNotificationEventType";
32
35
  import StatusPageSubscriberNotificationStatus from "../../Types/StatusPage/StatusPageSubscriberNotificationStatus";
33
36
  import DockerHost from "../../Models/DatabaseModels/DockerHost";
@@ -442,6 +445,8 @@ export class Service extends DatabaseService<Model> {
442
445
  updateBy.data.isVisibleOnStatusPage = false;
443
446
  }
444
447
 
448
+ await this.validateProjectScopedReferences(updateBy);
449
+
445
450
  const carryForward: UpdateCarryForward = {};
446
451
 
447
452
  if (
@@ -552,6 +557,90 @@ export class Service extends DatabaseService<Model> {
552
557
  };
553
558
  }
554
559
 
560
+ /*
561
+ * An update can repoint an incident at another project's state, severity or
562
+ * monitor status just as easily as a create can, and the result is the same:
563
+ * the referenced project can no longer be deleted. Only the columns actually
564
+ * being written are checked, so ordinary updates cost no extra queries.
565
+ */
566
+ private async validateProjectScopedReferences(
567
+ updateBy: UpdateBy<Model>,
568
+ ): Promise<void> {
569
+ const incidentStateId: ObjectID | string | undefined =
570
+ resolveReferenceId(updateBy.data.currentIncidentStateId) ||
571
+ resolveReferenceId(updateBy.data.currentIncidentState);
572
+
573
+ const incidentSeverityId: ObjectID | string | undefined =
574
+ resolveReferenceId(updateBy.data.incidentSeverityId) ||
575
+ resolveReferenceId(updateBy.data.incidentSeverity);
576
+
577
+ const changeMonitorStatusToId: ObjectID | string | undefined =
578
+ resolveReferenceId(updateBy.data.changeMonitorStatusToId) ||
579
+ resolveReferenceId(updateBy.data.changeMonitorStatusTo);
580
+
581
+ if (!incidentStateId && !incidentSeverityId && !changeMonitorStatusToId) {
582
+ return;
583
+ }
584
+
585
+ /*
586
+ * Root/API updates do not always carry a tenantId, so fall back to the
587
+ * project of each incident the query actually matches.
588
+ */
589
+ const projectIds: Array<ObjectID> = updateBy.props.tenantId
590
+ ? [updateBy.props.tenantId]
591
+ : await this.getProjectIdsForUpdateQuery(updateBy);
592
+
593
+ for (const projectId of projectIds) {
594
+ await ProjectScopedReferenceValidator.validateReferencesBelongToProject({
595
+ projectId: projectId,
596
+ subject: "incident",
597
+ references: [
598
+ {
599
+ modelName: "Incident State",
600
+ id: incidentStateId,
601
+ service: IncidentStateService,
602
+ },
603
+ {
604
+ modelName: "Incident Severity",
605
+ id: incidentSeverityId,
606
+ service: IncidentSeverityService,
607
+ },
608
+ {
609
+ modelName: "Monitor Status",
610
+ id: changeMonitorStatusToId,
611
+ service: MonitorStatusService,
612
+ },
613
+ ],
614
+ });
615
+ }
616
+ }
617
+
618
+ private async getProjectIdsForUpdateQuery(
619
+ updateBy: UpdateBy<Model>,
620
+ ): Promise<Array<ObjectID>> {
621
+ const incidents: Array<Model> = await this.findBy({
622
+ query: updateBy.query,
623
+ select: {
624
+ projectId: true,
625
+ },
626
+ limit: LIMIT_MAX,
627
+ skip: 0,
628
+ props: {
629
+ isRoot: true,
630
+ },
631
+ });
632
+
633
+ const projectIds: Dictionary<ObjectID> = {};
634
+
635
+ for (const incident of incidents) {
636
+ if (incident.projectId) {
637
+ projectIds[incident.projectId.toString()] = incident.projectId;
638
+ }
639
+ }
640
+
641
+ return Object.values(projectIds);
642
+ }
643
+
555
644
  @CaptureSpan()
556
645
  protected override async onBeforeCreate(
557
646
  createBy: CreateBy<Model>,
@@ -832,6 +921,40 @@ export class Service extends DatabaseService<Model> {
832
921
  initialIncidentStateId = incidentState.id;
833
922
  }
834
923
 
924
+ /*
925
+ * The severity and the monitor status to switch to can arrive from an API
926
+ * caller, an incident template or a monitor criteria, and none of those
927
+ * paths checked that the record belongs to this project. Persisting
928
+ * another project's id leaves that project undeletable, so reject it here.
929
+ * Runs before the counter increment so a rejected create does not burn an
930
+ * incident number.
931
+ */
932
+ await ProjectScopedReferenceValidator.validateReferencesBelongToProject({
933
+ projectId: projectId,
934
+ subject: "incident",
935
+ references: [
936
+ {
937
+ modelName: "Incident State",
938
+ id: initialIncidentStateId,
939
+ service: IncidentStateService,
940
+ },
941
+ {
942
+ modelName: "Incident Severity",
943
+ id:
944
+ resolveReferenceId(createBy.data.incidentSeverityId) ||
945
+ resolveReferenceId(createBy.data.incidentSeverity),
946
+ service: IncidentSeverityService,
947
+ },
948
+ {
949
+ modelName: "Monitor Status",
950
+ id:
951
+ resolveReferenceId(createBy.data.changeMonitorStatusToId) ||
952
+ resolveReferenceId(createBy.data.changeMonitorStatusTo),
953
+ service: MonitorStatusService,
954
+ },
955
+ ],
956
+ });
957
+
835
958
  const incidentCounterResult: {
836
959
  counter: number;
837
960
  prefix: string | undefined;
@@ -1,20 +1,142 @@
1
- import { OnCreate } from "../Types/Database/Hooks";
1
+ import { OnCreate, OnUpdate } from "../Types/Database/Hooks";
2
+ import CreateBy from "../Types/Database/CreateBy";
3
+ import UpdateBy from "../Types/Database/UpdateBy";
2
4
  import DatabaseService from "./DatabaseService";
3
5
  import IncidentTemplateOwnerTeamService from "./IncidentTemplateOwnerTeamService";
4
6
  import IncidentTemplateOwnerUserService from "./IncidentTemplateOwnerUserService";
7
+ import IncidentSeverityService from "./IncidentSeverityService";
8
+ import IncidentStateService from "./IncidentStateService";
9
+ import MonitorStatusService from "./MonitorStatusService";
5
10
  import DatabaseCommonInteractionProps from "../../Types/BaseDatabase/DatabaseCommonInteractionProps";
11
+ import LIMIT_MAX from "../../Types/Database/LimitMax";
12
+ import Dictionary from "../../Types/Dictionary";
6
13
  import ObjectID from "../../Types/ObjectID";
7
14
  import Typeof from "../../Types/Typeof";
8
15
  import Model from "../../Models/DatabaseModels/IncidentTemplate";
9
16
  import IncidentTemplateOwnerTeam from "../../Models/DatabaseModels/IncidentTemplateOwnerTeam";
10
17
  import IncidentTemplateOwnerUser from "../../Models/DatabaseModels/IncidentTemplateOwnerUser";
18
+ import ProjectScopedReferenceValidator, {
19
+ ProjectScopedReference,
20
+ resolveReferenceId,
21
+ } from "../Utils/Database/ProjectScopedReferenceValidator";
11
22
  import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
23
+ import QueryDeepPartialEntity from "../../Types/Database/PartialEntity";
12
24
 
13
25
  export class Service extends DatabaseService<Model> {
14
26
  public constructor() {
15
27
  super(Model);
16
28
  }
17
29
 
30
+ /*
31
+ * A template is copied onto every incident created from it, so an id
32
+ * belonging to another project here becomes a cross-project reference on
33
+ * each of those incidents — and the referenced project can then no longer be
34
+ * deleted. Reject it where it enters instead.
35
+ */
36
+ @CaptureSpan()
37
+ protected override async onBeforeCreate(
38
+ createBy: CreateBy<Model>,
39
+ ): Promise<OnCreate<Model>> {
40
+ const projectId: ObjectID | undefined =
41
+ createBy.props.tenantId || createBy.data.projectId;
42
+
43
+ await ProjectScopedReferenceValidator.validateReferencesBelongToProject({
44
+ projectId: projectId,
45
+ subject: "incident template",
46
+ references: this.getProjectScopedReferences(createBy.data),
47
+ });
48
+
49
+ return { createBy, carryForward: null };
50
+ }
51
+
52
+ @CaptureSpan()
53
+ protected override async onBeforeUpdate(
54
+ updateBy: UpdateBy<Model>,
55
+ ): Promise<OnUpdate<Model>> {
56
+ const references: Array<ProjectScopedReference> =
57
+ this.getProjectScopedReferences(updateBy.data);
58
+
59
+ if (
60
+ references.every((reference: ProjectScopedReference) => {
61
+ return !reference.id;
62
+ })
63
+ ) {
64
+ return { updateBy, carryForward: null };
65
+ }
66
+
67
+ /*
68
+ * Root/API updates do not always carry a tenantId, so fall back to the
69
+ * project of each template the query actually matches.
70
+ */
71
+ const projectIds: Array<ObjectID> = updateBy.props.tenantId
72
+ ? [updateBy.props.tenantId]
73
+ : await this.getProjectIdsForUpdateQuery(updateBy);
74
+
75
+ for (const projectId of projectIds) {
76
+ await ProjectScopedReferenceValidator.validateReferencesBelongToProject({
77
+ projectId: projectId,
78
+ subject: "incident template",
79
+ references: references,
80
+ });
81
+ }
82
+
83
+ return { updateBy, carryForward: null };
84
+ }
85
+
86
+ private getProjectScopedReferences(
87
+ data: Model | QueryDeepPartialEntity<Model>,
88
+ ): Array<ProjectScopedReference> {
89
+ return [
90
+ {
91
+ modelName: "Incident State",
92
+ id:
93
+ resolveReferenceId(data.initialIncidentStateId) ||
94
+ resolveReferenceId(data.initialIncidentState),
95
+ service: IncidentStateService,
96
+ },
97
+ {
98
+ modelName: "Incident Severity",
99
+ id:
100
+ resolveReferenceId(data.incidentSeverityId) ||
101
+ resolveReferenceId(data.incidentSeverity),
102
+ service: IncidentSeverityService,
103
+ },
104
+ {
105
+ modelName: "Monitor Status",
106
+ id:
107
+ resolveReferenceId(data.changeMonitorStatusToId) ||
108
+ resolveReferenceId(data.changeMonitorStatusTo),
109
+ service: MonitorStatusService,
110
+ },
111
+ ];
112
+ }
113
+
114
+ private async getProjectIdsForUpdateQuery(
115
+ updateBy: UpdateBy<Model>,
116
+ ): Promise<Array<ObjectID>> {
117
+ const templates: Array<Model> = await this.findBy({
118
+ query: updateBy.query,
119
+ select: {
120
+ projectId: true,
121
+ },
122
+ limit: LIMIT_MAX,
123
+ skip: 0,
124
+ props: {
125
+ isRoot: true,
126
+ },
127
+ });
128
+
129
+ const projectIds: Dictionary<ObjectID> = {};
130
+
131
+ for (const template of templates) {
132
+ if (template.projectId) {
133
+ projectIds[template.projectId.toString()] = template.projectId;
134
+ }
135
+ }
136
+
137
+ return Object.values(projectIds);
138
+ }
139
+
18
140
  @CaptureSpan()
19
141
  protected override async onCreateSuccess(
20
142
  onCreate: OnCreate<Model>,
@@ -134,6 +134,7 @@ import EnterpriseLicenseService from "./EnterpriseLicenseService";
134
134
  import EnterpriseLicenseInstanceService from "./EnterpriseLicenseInstanceService";
135
135
  import MarketingConversionService from "./MarketingConversionService";
136
136
  import OpenSourceDeploymentService from "./OpenSourceDeploymentService";
137
+ import RecommendationDismissalService from "./RecommendationDismissalService";
137
138
  import ResellerPlanService from "./ResellerPlanService";
138
139
  import ResellerService from "./ResellerService";
139
140
  import ScheduledMaintenanceCustomFieldService from "./ScheduledMaintenanceCustomFieldService";
@@ -286,6 +287,7 @@ const services: Array<BaseService> = [
286
287
 
287
288
  ResellerService,
288
289
  ResellerPlanService,
290
+ RecommendationDismissalService,
289
291
  // Import all services in current folder here.
290
292
  AccessTokenService,
291
293
  ApiKeyPermissionService,
@@ -1,10 +1,143 @@
1
1
  import DatabaseService from "./DatabaseService";
2
2
  import Model from "../../Models/DatabaseModels/LogDropFilter";
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: "logs",
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
+ * log records batched into one UPDATE), never once per record, and never
119
+ * on the request path. Runs no hooks and does not bump `version`, so it
120
+ * cannot 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();
@@ -1,6 +1,7 @@
1
1
  import ObjectID from "../../Types/ObjectID";
2
2
  import CreateBy from "../Types/Database/CreateBy";
3
- import { OnCreate, OnUpdate } from "../Types/Database/Hooks";
3
+ import DeleteBy from "../Types/Database/DeleteBy";
4
+ import { OnCreate, OnDelete, OnUpdate } from "../Types/Database/Hooks";
4
5
  import DatabaseService, { EntityManager } from "./DatabaseService";
5
6
  import OneUptimeDate from "../../Types/Date";
6
7
  import BadDataException from "../../Types/Exception/BadDataException";
@@ -9,6 +10,7 @@ import Monitor from "../../Models/DatabaseModels/Monitor";
9
10
  import QueryHelper from "../Types/Database/QueryHelper";
10
11
  import { LIMIT_PER_PROJECT } from "../../Types/Database/LimitMax";
11
12
  import MonitorService from "./MonitorService";
13
+ import ProbeService from "./ProbeService";
12
14
  import { MonitorTypeHelper } from "../../Types/Monitor/MonitorType";
13
15
  import CronTab from "../Utils/CronTab";
14
16
  import logger, { LogAttributes } from "../Utils/Logger";
@@ -270,6 +272,31 @@ export class Service extends DatabaseService<MonitorProbe> {
270
272
  }
271
273
  }
272
274
 
275
+ /*
276
+ * The probe id on a create comes straight from the browser (the
277
+ * Monitor > Probes table posts it), so it has to be checked against the
278
+ * tenant exactly like the monitor-create path does - otherwise another
279
+ * project's probe can be attached to this monitor.
280
+ */
281
+ const probeId: ObjectID | undefined | null =
282
+ createBy.data.probeId || createBy.data.probe?.id;
283
+ const projectId: ObjectID | undefined | null =
284
+ createBy.data.projectId || createBy.data.project?.id;
285
+
286
+ if (probeId && projectId) {
287
+ const isProbeAttachable: boolean =
288
+ await ProbeService.isProbeAttachableToProject({
289
+ probeId: probeId,
290
+ projectId: projectId,
291
+ });
292
+
293
+ if (!isProbeAttachable) {
294
+ throw new BadDataException(
295
+ "Probe not found or it does not belong to this project.",
296
+ );
297
+ }
298
+ }
299
+
273
300
  // Check if the monitor type supports probes
274
301
  const monitorId: ObjectID | undefined | null =
275
302
  createBy.data.monitorId || createBy.data.monitor?.id;
@@ -362,12 +389,75 @@ export class Service extends DatabaseService<MonitorProbe> {
362
389
  return onUpdate;
363
390
  }
364
391
 
392
+ /*
393
+ * Removing a probe from a monitor changes the same aggregate that adding one
394
+ * or toggling isEnabled changes - Monitor.isNoProbeEnabledOnThisMonitor and
395
+ * isAllProbesDisconnectedFromThisMonitor. Without these hooks, deleting the
396
+ * last probe left the monitor claiming it was still being watched: no
397
+ * "Probes Not Enabled" banner and no owner notification, even though nothing
398
+ * was monitoring it any more.
399
+ *
400
+ * The monitorIds have to be read before the delete, because after it the
401
+ * rows are gone.
402
+ */
403
+ protected override async onBeforeDelete(
404
+ deleteBy: DeleteBy<MonitorProbe>,
405
+ ): Promise<OnDelete<MonitorProbe>> {
406
+ const itemsToDelete: Array<MonitorProbe> = await this.findBy({
407
+ query: deleteBy.query,
408
+ limit: deleteBy.limit,
409
+ skip: deleteBy.skip,
410
+ select: {
411
+ monitorId: true,
412
+ },
413
+ props: {
414
+ isRoot: true,
415
+ },
416
+ });
417
+
418
+ return {
419
+ deleteBy,
420
+ carryForward: {
421
+ monitorIds: itemsToDelete
422
+ .map((item: MonitorProbe) => {
423
+ return item.monitorId;
424
+ })
425
+ .filter((monitorId: ObjectID | undefined) => {
426
+ return Boolean(monitorId);
427
+ }) as Array<ObjectID>,
428
+ },
429
+ };
430
+ }
431
+
432
+ protected override async onDeleteSuccess(
433
+ onDelete: OnDelete<MonitorProbe>,
434
+ _itemIdsBeforeDelete: Array<ObjectID>,
435
+ ): Promise<OnDelete<MonitorProbe>> {
436
+ const monitorIds: Array<ObjectID> =
437
+ (onDelete.carryForward?.monitorIds as Array<ObjectID>) || [];
438
+
439
+ const refreshedMonitorIds: Set<string> = new Set();
440
+
441
+ for (const monitorId of monitorIds) {
442
+ // A bulk delete can touch the same monitor many times over.
443
+ if (refreshedMonitorIds.has(monitorId.toString())) {
444
+ continue;
445
+ }
446
+
447
+ refreshedMonitorIds.add(monitorId.toString());
448
+
449
+ await this.refreshMonitorStatusSafely(monitorId);
450
+ }
451
+
452
+ return onDelete;
453
+ }
454
+
365
455
  /*
366
456
  * Refresh a single monitor's aggregate probe status without letting a
367
457
  * failure bubble up. These refreshes run in post-commit hooks
368
- * (onCreateSuccess / onUpdateSuccess) after the MonitorProbe row is already
369
- * persisted, so a status-refresh error must not turn a successful save into
370
- * a 500 for the user — log it instead.
458
+ * (onCreateSuccess / onUpdateSuccess / onDeleteSuccess) after the
459
+ * MonitorProbe row is already persisted, so a status-refresh error must not
460
+ * turn a successful save into a 500 for the user — log it instead.
371
461
  */
372
462
  private async refreshMonitorStatusSafely(monitorId: ObjectID): Promise<void> {
373
463
  try {