@oneuptime/common 11.7.3 → 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 (365) hide show
  1. package/Models/DatabaseModels/AlertEpisodeStateTimeline.ts +1 -0
  2. package/Models/DatabaseModels/AlertStateTimeline.ts +1 -0
  3. package/Models/DatabaseModels/IncidentEpisodeStateTimeline.ts +1 -0
  4. package/Models/DatabaseModels/IncidentStateTimeline.ts +1 -0
  5. package/Models/DatabaseModels/Index.ts +5 -0
  6. package/Models/DatabaseModels/LogDropFilter.ts +89 -0
  7. package/Models/DatabaseModels/NetworkDeviceDiscoveryScan.ts +13 -3
  8. package/Models/DatabaseModels/RecommendationDismissal.ts +463 -0
  9. package/Models/DatabaseModels/ScheduledMaintenanceStateTimeline.ts +1 -0
  10. package/Models/DatabaseModels/StatusPageGroup.ts +95 -0
  11. package/Models/DatabaseModels/TraceDropFilter.ts +89 -0
  12. package/Models/DatabaseModels/WorkflowVariable.ts +5 -1
  13. package/Server/API/AlertAPI.ts +32 -17
  14. package/Server/API/BaseAPI.ts +31 -2
  15. package/Server/API/BaseAnalyticsAPI.ts +36 -2
  16. package/Server/API/CommonAPI.ts +57 -0
  17. package/Server/API/IncidentAPI.ts +60 -33
  18. package/Server/API/IncidentEpisodeAPI.ts +31 -16
  19. package/Server/API/MonitorAPI.ts +30 -0
  20. package/Server/API/MonitorTemplateAPI.ts +8 -0
  21. package/Server/API/ProbeAPI.ts +196 -15
  22. package/Server/API/ProjectAPI.ts +79 -1
  23. package/Server/API/ScheduledMaintenanceAPI.ts +33 -18
  24. package/Server/API/StatusPageAPI.ts +74 -37
  25. package/Server/API/WorkspaceNotificationRuleAPI.ts +34 -4
  26. package/Server/Infrastructure/Postgres/SchemaMigrations/1785320000000-RepairCrossProjectIncidentReferences.ts +527 -0
  27. package/Server/Infrastructure/Postgres/SchemaMigrations/1785329453269-AddParentGroupToStatusPageGroup.ts +31 -0
  28. package/Server/Infrastructure/Postgres/SchemaMigrations/1785397674289-AddRecommendationDismissalTable.ts +55 -0
  29. package/Server/Infrastructure/Postgres/SchemaMigrations/1785405581596-AddDroppedCountersToDropFilters.ts +53 -0
  30. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +8 -0
  31. package/Server/Services/AlertEpisodeService.ts +47 -0
  32. package/Server/Services/AlertService.ts +125 -0
  33. package/Server/Services/BillingService.ts +98 -0
  34. package/Server/Services/DatabaseService.ts +184 -20
  35. package/Server/Services/IncidentEpisodeService.ts +47 -0
  36. package/Server/Services/IncidentService.ts +123 -0
  37. package/Server/Services/IncidentTemplateService.ts +123 -1
  38. package/Server/Services/Index.ts +2 -0
  39. package/Server/Services/LogDropFilterService.ts +133 -0
  40. package/Server/Services/MonitorProbeService.ts +94 -4
  41. package/Server/Services/MonitorService.ts +48 -43
  42. package/Server/Services/NetworkDeviceDiscoveryScanService.ts +70 -0
  43. package/Server/Services/ProbeService.ts +66 -0
  44. package/Server/Services/ProjectService.ts +131 -7
  45. package/Server/Services/RecommendationDismissalService.ts +52 -0
  46. package/Server/Services/RunbookAgentJobService.ts +68 -7
  47. package/Server/Services/ScheduledMaintenanceService.ts +103 -0
  48. package/Server/Services/ScheduledMaintenanceTemplateService.ts +90 -0
  49. package/Server/Services/StatusPageGroupService.ts +186 -0
  50. package/Server/Services/TraceDropFilterService.ts +133 -0
  51. package/Server/Types/Workflow/Components/API/Delete.ts +12 -0
  52. package/Server/Types/Workflow/Components/API/Get.ts +12 -0
  53. package/Server/Types/Workflow/Components/API/Patch.ts +12 -0
  54. package/Server/Types/Workflow/Components/API/Post.ts +12 -0
  55. package/Server/Types/Workflow/Components/API/Put.ts +13 -0
  56. package/Server/Utils/Database/ProjectScopedReferenceValidator.ts +212 -0
  57. package/Server/Utils/DropFilterValidation.ts +127 -0
  58. package/Server/Utils/Errors.ts +5 -0
  59. package/Server/Utils/Monitor/MonitorAlert.ts +28 -1
  60. package/Server/Utils/Monitor/MonitorIncident.ts +31 -2
  61. package/Server/Utils/Telemetry/AppMetrics.ts +31 -0
  62. package/Tests/Models/DatabaseModels/MonitorProbeColumnAccessControl.test.ts +196 -0
  63. package/Tests/Models/RecommendationDismissalModel.test.ts +269 -0
  64. package/Tests/Server/API/BaseAPIUpdatePayloadValidation.test.ts +320 -0
  65. package/Tests/Server/API/BaseAnalyticsAPIUpdatePayloadValidation.test.ts +293 -0
  66. package/Tests/Server/API/CommonAPIAuthGuard.test.ts +164 -0
  67. package/Tests/Server/API/ProbeAPI.test.ts +422 -53
  68. package/Tests/Server/API/ProjectAPI.test.ts +180 -0
  69. package/Tests/Server/API/ProjectAPIExtendTrialBillingDisabled.test.ts +138 -0
  70. package/Tests/Server/API/ProjectScopedCustomRouteAuth.test.ts +458 -0
  71. package/Tests/Server/Infrastructure/ContainerBootConfiguration.test.ts +359 -0
  72. package/Tests/Server/Infrastructure/ProcessSignalDelivery.test.ts +427 -0
  73. package/Tests/Server/Services/BillingServiceExtendTrial.test.ts +439 -0
  74. package/Tests/Server/Services/CrossProjectReferenceWriteGuard.test.ts +810 -0
  75. package/Tests/Server/Services/DatabaseServiceAtomicAddToColumns.test.ts +269 -0
  76. package/Tests/Server/Services/DatabaseServiceEmptyUpdate.test.ts +277 -0
  77. package/Tests/Server/Services/DatabaseServiceSortColumnSelect.test.ts +201 -0
  78. package/Tests/Server/Services/DiscoveryScanClaimHookFreeSafety.test.ts +81 -23
  79. package/Tests/Server/Services/DropFilterSaveValidation.test.ts +398 -0
  80. package/Tests/Server/Services/MonitorProbeDeleteHooks.test.ts +280 -0
  81. package/Tests/Server/Services/MonitorProbeServiceProbeTenancy.test.ts +304 -0
  82. package/Tests/Server/Services/NetworkDeviceDiscoveryScanService.test.ts +262 -0
  83. package/Tests/Server/Services/ProjectServiceExtendTrial.test.ts +614 -0
  84. package/Tests/Server/Services/RecommendationDismissalService.test.ts +306 -0
  85. package/Tests/Server/Services/RepairCrossProjectIncidentReferencesMigration.test.ts +528 -0
  86. package/Tests/Server/Services/StatusPageGroupNesting.test.ts +395 -0
  87. package/Tests/Server/TestingUtils/Services/BillingServiceHelper.ts +26 -21
  88. package/Tests/Server/Types/Database/Permissions/WorkflowVariableColumnPermission.test.ts +227 -0
  89. package/Tests/Server/Types/Workflow/Components/ApiComponentErrorPort.test.ts +285 -0
  90. package/Tests/Server/Utils/Database/ProjectScopedReferenceValidator.test.ts +463 -0
  91. package/Tests/Server/Utils/DropFilterValidation.test.ts +269 -0
  92. package/Tests/Server/Utils/Telemetry/SpanUtil.test.ts +94 -0
  93. package/Tests/Types/DateUserTimezone.test.ts +52 -0
  94. package/Tests/Types/Monitor/KubernetesAlertTemplates.test.ts +177 -9
  95. package/Tests/Types/Monitor/MonitorStepDnsMonitor.test.ts +105 -0
  96. package/Tests/Types/Monitor/MonitorStepDnssecMonitor.test.ts +131 -0
  97. package/Tests/Types/Monitor/MonitorStepDomainMonitor.test.ts +60 -0
  98. package/Tests/Types/Monitor/MonitorStepExternalStatusPageMonitor.test.ts +82 -0
  99. package/Tests/Types/Monitor/MonitorStepInfrastructureMonitors.test.ts +268 -0
  100. package/Tests/Types/Monitor/MonitorStepMetricMonitor.test.ts +386 -0
  101. package/Tests/Types/Monitor/MonitorStepProfileMonitor.test.ts +185 -0
  102. package/Tests/Types/Monitor/MonitorStepSnmpMonitor.test.ts +156 -0
  103. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationCatalog.test.ts +371 -0
  104. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationCoverage.test.ts +901 -0
  105. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationNotificationMode.test.ts +607 -0
  106. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.test.ts +754 -0
  107. package/Tests/Types/Monitor/Recommendation/MonitorRecommendationUtil.test.ts +960 -0
  108. package/Tests/Types/RollingTime/RollingTimeUtil.test.ts +186 -0
  109. package/Tests/Types/Runbook/RunbookStepTimeout.test.ts +410 -0
  110. package/Tests/Types/Telemetry/DropFilterSampling.test.ts +241 -0
  111. package/Tests/Types/Workspace/NotificationRuleConditionUtil.test.ts +353 -0
  112. package/Tests/Types/Workspace/NotificationRuleUtil.test.ts +566 -0
  113. package/Tests/UI/Components/CodeEditor.test.tsx +174 -0
  114. package/Tests/UI/Components/ErrorBoundary.test.tsx +555 -24
  115. package/Tests/UI/Components/InfoCard.test.tsx +358 -0
  116. package/Tests/UI/Components/LogTimeRangePicker.test.tsx +138 -0
  117. package/Tests/UI/Components/Modal.test.tsx +43 -5
  118. package/Tests/UI/Components/ModelTable/BaseModelTableSearchLabels.test.tsx +397 -0
  119. package/Tests/UI/Components/ModelTable/ColumnCustomizationModal.test.tsx +427 -0
  120. package/Tests/UI/Components/Runbook/StepTimeoutInput.test.tsx +386 -0
  121. package/Tests/UI/Components/StatusPage/ResourceGroupSection.test.tsx +671 -0
  122. package/Tests/UI/Components/TelemetryTimeRangePicker.test.tsx +404 -0
  123. package/Tests/UI/Utils/DropdownAlignment.test.ts +306 -0
  124. package/Tests/UI/Utils/TableFilterUrlState.test.ts +292 -0
  125. package/Tests/Utils/Monitor/MonitorSummaryProbeUtil.test.ts +263 -0
  126. package/Tests/Utils/NetworkDiscovery/ScanTargetUtil.test.ts +583 -0
  127. package/Tests/Utils/StatusPage/GroupNestingLayout.test.ts +1072 -0
  128. package/Tests/Utils/StatusPage/GroupTree.test.ts +583 -0
  129. package/Tests/Utils/StatusPage/ResourceUptime.test.ts +411 -0
  130. package/Types/Date.ts +15 -6
  131. package/Types/Monitor/KubernetesAlertTemplates.ts +205 -0
  132. package/Types/Monitor/MonitorStep.ts +10 -1
  133. package/Types/Monitor/MonitorStepMetricMonitor.ts +46 -1
  134. package/Types/Monitor/Recommendation/MonitorRecommendationCatalog.ts +413 -0
  135. package/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.ts +168 -0
  136. package/Types/Monitor/Recommendation/MonitorRecommendationTypes.ts +175 -0
  137. package/Types/Monitor/Recommendation/MonitorRecommendationUtil.ts +743 -0
  138. package/Types/Permission.ts +45 -0
  139. package/Types/Recommendation/RecommendationType.ts +20 -0
  140. package/Types/Runbook/RunbookExecutionDeadline.ts +129 -0
  141. package/Types/Runbook/RunbookStepTimeout.ts +202 -0
  142. package/Types/Telemetry/DropFilterSampling.ts +92 -0
  143. package/UI/Components/AI/GenerateFromAIModal.tsx +0 -2
  144. package/UI/Components/Accordion/Accordion.tsx +10 -2
  145. package/UI/Components/BulkUpdate/BulkLabelActions.tsx +0 -1
  146. package/UI/Components/CodeEditor/CodeEditor.tsx +34 -20
  147. package/UI/Components/Date/RangeStartAndEndDateView.tsx +0 -1
  148. package/UI/Components/EditionLabel/EditionLabel.tsx +1 -27
  149. package/UI/Components/Error/PageError.tsx +0 -4
  150. package/UI/Components/ErrorBoundary.tsx +252 -15
  151. package/UI/Components/InfoCard/InfoCard.tsx +58 -1
  152. package/UI/Components/LogsViewer/components/LogTimeRangePicker.tsx +34 -1
  153. package/UI/Components/Modal/Modal.tsx +16 -60
  154. package/UI/Components/ModelFormModal/ModelFormModal.tsx +0 -8
  155. package/UI/Components/ModelTable/BaseModelTable.tsx +116 -67
  156. package/UI/Components/ModelTable/ColumnCustomizationModal.tsx +150 -47
  157. package/UI/Components/Runbook/StepTimeoutInput.tsx +173 -0
  158. package/UI/Components/StatusPage/ResourceGroupSection.tsx +231 -0
  159. package/UI/Components/TelemetryViewer/components/TelemetryTimeRangePicker.tsx +34 -1
  160. package/UI/Utils/DropdownAlignment.ts +162 -0
  161. package/UI/Utils/TableFilterUrlState.ts +59 -20
  162. package/Utils/API.ts +106 -2
  163. package/Utils/Monitor/MonitorSummaryProbeUtil.ts +130 -0
  164. package/Utils/NetworkDiscovery/ScanTargetUtil.ts +434 -0
  165. package/Utils/StatusPage/GroupNestingLayout.ts +343 -0
  166. package/Utils/StatusPage/GroupTree.ts +307 -0
  167. package/Utils/StatusPage/ResourceUptime.ts +90 -17
  168. package/build/dist/Models/DatabaseModels/AlertEpisodeStateTimeline.js +1 -0
  169. package/build/dist/Models/DatabaseModels/AlertEpisodeStateTimeline.js.map +1 -1
  170. package/build/dist/Models/DatabaseModels/AlertStateTimeline.js +1 -0
  171. package/build/dist/Models/DatabaseModels/AlertStateTimeline.js.map +1 -1
  172. package/build/dist/Models/DatabaseModels/IncidentEpisodeStateTimeline.js +1 -0
  173. package/build/dist/Models/DatabaseModels/IncidentEpisodeStateTimeline.js.map +1 -1
  174. package/build/dist/Models/DatabaseModels/IncidentStateTimeline.js +1 -0
  175. package/build/dist/Models/DatabaseModels/IncidentStateTimeline.js.map +1 -1
  176. package/build/dist/Models/DatabaseModels/Index.js +2 -0
  177. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  178. package/build/dist/Models/DatabaseModels/LogDropFilter.js +91 -0
  179. package/build/dist/Models/DatabaseModels/LogDropFilter.js.map +1 -1
  180. package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js +14 -4
  181. package/build/dist/Models/DatabaseModels/NetworkDeviceDiscoveryScan.js.map +1 -1
  182. package/build/dist/Models/DatabaseModels/RecommendationDismissal.js +484 -0
  183. package/build/dist/Models/DatabaseModels/RecommendationDismissal.js.map +1 -0
  184. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceStateTimeline.js +1 -0
  185. package/build/dist/Models/DatabaseModels/ScheduledMaintenanceStateTimeline.js.map +1 -1
  186. package/build/dist/Models/DatabaseModels/StatusPageGroup.js +94 -0
  187. package/build/dist/Models/DatabaseModels/StatusPageGroup.js.map +1 -1
  188. package/build/dist/Models/DatabaseModels/TraceDropFilter.js +91 -0
  189. package/build/dist/Models/DatabaseModels/TraceDropFilter.js.map +1 -1
  190. package/build/dist/Models/DatabaseModels/WorkflowVariable.js +5 -1
  191. package/build/dist/Models/DatabaseModels/WorkflowVariable.js.map +1 -1
  192. package/build/dist/Server/API/AlertAPI.js +22 -13
  193. package/build/dist/Server/API/AlertAPI.js.map +1 -1
  194. package/build/dist/Server/API/BaseAPI.js +22 -1
  195. package/build/dist/Server/API/BaseAPI.js.map +1 -1
  196. package/build/dist/Server/API/BaseAnalyticsAPI.js +24 -1
  197. package/build/dist/Server/API/BaseAnalyticsAPI.js.map +1 -1
  198. package/build/dist/Server/API/CommonAPI.js +42 -0
  199. package/build/dist/Server/API/CommonAPI.js.map +1 -1
  200. package/build/dist/Server/API/IncidentAPI.js +43 -26
  201. package/build/dist/Server/API/IncidentAPI.js.map +1 -1
  202. package/build/dist/Server/API/IncidentEpisodeAPI.js +21 -12
  203. package/build/dist/Server/API/IncidentEpisodeAPI.js.map +1 -1
  204. package/build/dist/Server/API/MonitorAPI.js +23 -0
  205. package/build/dist/Server/API/MonitorAPI.js.map +1 -1
  206. package/build/dist/Server/API/MonitorTemplateAPI.js +4 -0
  207. package/build/dist/Server/API/MonitorTemplateAPI.js.map +1 -1
  208. package/build/dist/Server/API/ProbeAPI.js +131 -15
  209. package/build/dist/Server/API/ProbeAPI.js.map +1 -1
  210. package/build/dist/Server/API/ProjectAPI.js +62 -3
  211. package/build/dist/Server/API/ProjectAPI.js.map +1 -1
  212. package/build/dist/Server/API/ScheduledMaintenanceAPI.js +23 -14
  213. package/build/dist/Server/API/ScheduledMaintenanceAPI.js.map +1 -1
  214. package/build/dist/Server/API/StatusPageAPI.js +61 -33
  215. package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
  216. package/build/dist/Server/API/WorkspaceNotificationRuleAPI.js +26 -2
  217. package/build/dist/Server/API/WorkspaceNotificationRuleAPI.js.map +1 -1
  218. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785320000000-RepairCrossProjectIncidentReferences.js +397 -0
  219. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785320000000-RepairCrossProjectIncidentReferences.js.map +1 -0
  220. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785329453269-AddParentGroupToStatusPageGroup.js +16 -0
  221. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785329453269-AddParentGroupToStatusPageGroup.js.map +1 -0
  222. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785397674289-AddRecommendationDismissalTable.js +30 -0
  223. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785397674289-AddRecommendationDismissalTable.js.map +1 -0
  224. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785405581596-AddDroppedCountersToDropFilters.js +34 -0
  225. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1785405581596-AddDroppedCountersToDropFilters.js.map +1 -0
  226. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +8 -0
  227. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  228. package/build/dist/Server/Services/AlertEpisodeService.js +39 -0
  229. package/build/dist/Server/Services/AlertEpisodeService.js.map +1 -1
  230. package/build/dist/Server/Services/AlertService.js +95 -0
  231. package/build/dist/Server/Services/AlertService.js.map +1 -1
  232. package/build/dist/Server/Services/BillingService.js +71 -0
  233. package/build/dist/Server/Services/BillingService.js.map +1 -1
  234. package/build/dist/Server/Services/DatabaseService.js +140 -17
  235. package/build/dist/Server/Services/DatabaseService.js.map +1 -1
  236. package/build/dist/Server/Services/IncidentEpisodeService.js +39 -0
  237. package/build/dist/Server/Services/IncidentEpisodeService.js.map +1 -1
  238. package/build/dist/Server/Services/IncidentService.js +100 -0
  239. package/build/dist/Server/Services/IncidentService.js.map +1 -1
  240. package/build/dist/Server/Services/IncidentTemplateService.js +97 -0
  241. package/build/dist/Server/Services/IncidentTemplateService.js.map +1 -1
  242. package/build/dist/Server/Services/Index.js +2 -0
  243. package/build/dist/Server/Services/Index.js.map +1 -1
  244. package/build/dist/Server/Services/LogDropFilterService.js +93 -0
  245. package/build/dist/Server/Services/LogDropFilterService.js.map +1 -1
  246. package/build/dist/Server/Services/MonitorProbeService.js +73 -5
  247. package/build/dist/Server/Services/MonitorProbeService.js.map +1 -1
  248. package/build/dist/Server/Services/MonitorService.js +34 -39
  249. package/build/dist/Server/Services/MonitorService.js.map +1 -1
  250. package/build/dist/Server/Services/NetworkDeviceDiscoveryScanService.js +71 -0
  251. package/build/dist/Server/Services/NetworkDeviceDiscoveryScanService.js.map +1 -1
  252. package/build/dist/Server/Services/ProbeService.js +64 -0
  253. package/build/dist/Server/Services/ProbeService.js.map +1 -1
  254. package/build/dist/Server/Services/ProjectService.js +103 -7
  255. package/build/dist/Server/Services/ProjectService.js.map +1 -1
  256. package/build/dist/Server/Services/RecommendationDismissalService.js +50 -0
  257. package/build/dist/Server/Services/RecommendationDismissalService.js.map +1 -0
  258. package/build/dist/Server/Services/RunbookAgentJobService.js +63 -5
  259. package/build/dist/Server/Services/RunbookAgentJobService.js.map +1 -1
  260. package/build/dist/Server/Services/ScheduledMaintenanceService.js +83 -0
  261. package/build/dist/Server/Services/ScheduledMaintenanceService.js.map +1 -1
  262. package/build/dist/Server/Services/ScheduledMaintenanceTemplateService.js +65 -0
  263. package/build/dist/Server/Services/ScheduledMaintenanceTemplateService.js.map +1 -1
  264. package/build/dist/Server/Services/StatusPageGroupService.js +136 -0
  265. package/build/dist/Server/Services/StatusPageGroupService.js.map +1 -1
  266. package/build/dist/Server/Services/TraceDropFilterService.js +93 -0
  267. package/build/dist/Server/Services/TraceDropFilterService.js.map +1 -1
  268. package/build/dist/Server/Types/Workflow/Components/API/Delete.js +11 -0
  269. package/build/dist/Server/Types/Workflow/Components/API/Delete.js.map +1 -1
  270. package/build/dist/Server/Types/Workflow/Components/API/Get.js +11 -0
  271. package/build/dist/Server/Types/Workflow/Components/API/Get.js.map +1 -1
  272. package/build/dist/Server/Types/Workflow/Components/API/Patch.js +11 -0
  273. package/build/dist/Server/Types/Workflow/Components/API/Patch.js.map +1 -1
  274. package/build/dist/Server/Types/Workflow/Components/API/Post.js +11 -0
  275. package/build/dist/Server/Types/Workflow/Components/API/Post.js.map +1 -1
  276. package/build/dist/Server/Types/Workflow/Components/API/Put.js +12 -0
  277. package/build/dist/Server/Types/Workflow/Components/API/Put.js.map +1 -1
  278. package/build/dist/Server/Utils/Database/ProjectScopedReferenceValidator.js +132 -0
  279. package/build/dist/Server/Utils/Database/ProjectScopedReferenceValidator.js.map +1 -0
  280. package/build/dist/Server/Utils/DropFilterValidation.js +80 -0
  281. package/build/dist/Server/Utils/DropFilterValidation.js.map +1 -0
  282. package/build/dist/Server/Utils/Errors.js +3 -0
  283. package/build/dist/Server/Utils/Errors.js.map +1 -1
  284. package/build/dist/Server/Utils/Monitor/MonitorAlert.js +30 -12
  285. package/build/dist/Server/Utils/Monitor/MonitorAlert.js.map +1 -1
  286. package/build/dist/Server/Utils/Monitor/MonitorIncident.js +38 -18
  287. package/build/dist/Server/Utils/Monitor/MonitorIncident.js.map +1 -1
  288. package/build/dist/Server/Utils/Telemetry/AppMetrics.js +26 -0
  289. package/build/dist/Server/Utils/Telemetry/AppMetrics.js.map +1 -1
  290. package/build/dist/Types/Date.js +14 -4
  291. package/build/dist/Types/Date.js.map +1 -1
  292. package/build/dist/Types/Monitor/KubernetesAlertTemplates.js +192 -0
  293. package/build/dist/Types/Monitor/KubernetesAlertTemplates.js.map +1 -1
  294. package/build/dist/Types/Monitor/MonitorStep.js +6 -1
  295. package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
  296. package/build/dist/Types/Monitor/MonitorStepMetricMonitor.js +32 -1
  297. package/build/dist/Types/Monitor/MonitorStepMetricMonitor.js.map +1 -1
  298. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js +294 -0
  299. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationCatalog.js.map +1 -0
  300. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.js +110 -0
  301. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationSeverityMapper.js.map +1 -0
  302. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js +58 -0
  303. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationTypes.js.map +1 -0
  304. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationUtil.js +451 -0
  305. package/build/dist/Types/Monitor/Recommendation/MonitorRecommendationUtil.js.map +1 -0
  306. package/build/dist/Types/Permission.js +40 -0
  307. package/build/dist/Types/Permission.js.map +1 -1
  308. package/build/dist/Types/Recommendation/RecommendationType.js +21 -0
  309. package/build/dist/Types/Recommendation/RecommendationType.js.map +1 -0
  310. package/build/dist/Types/Runbook/RunbookExecutionDeadline.js +93 -0
  311. package/build/dist/Types/Runbook/RunbookExecutionDeadline.js.map +1 -0
  312. package/build/dist/Types/Runbook/RunbookStepTimeout.js +142 -0
  313. package/build/dist/Types/Runbook/RunbookStepTimeout.js.map +1 -0
  314. package/build/dist/Types/Telemetry/DropFilterSampling.js +75 -0
  315. package/build/dist/Types/Telemetry/DropFilterSampling.js.map +1 -0
  316. package/build/dist/UI/Components/AI/GenerateFromAIModal.js +1 -2
  317. package/build/dist/UI/Components/AI/GenerateFromAIModal.js.map +1 -1
  318. package/build/dist/UI/Components/Accordion/Accordion.js +9 -2
  319. package/build/dist/UI/Components/Accordion/Accordion.js.map +1 -1
  320. package/build/dist/UI/Components/BulkUpdate/BulkLabelActions.js +1 -1
  321. package/build/dist/UI/Components/BulkUpdate/BulkLabelActions.js.map +1 -1
  322. package/build/dist/UI/Components/CodeEditor/CodeEditor.js +27 -14
  323. package/build/dist/UI/Components/CodeEditor/CodeEditor.js.map +1 -1
  324. package/build/dist/UI/Components/Date/RangeStartAndEndDateView.js +1 -1
  325. package/build/dist/UI/Components/Date/RangeStartAndEndDateView.js.map +1 -1
  326. package/build/dist/UI/Components/EditionLabel/EditionLabel.js +2 -20
  327. package/build/dist/UI/Components/EditionLabel/EditionLabel.js.map +1 -1
  328. package/build/dist/UI/Components/Error/PageError.js +1 -3
  329. package/build/dist/UI/Components/Error/PageError.js.map +1 -1
  330. package/build/dist/UI/Components/ErrorBoundary.js +145 -11
  331. package/build/dist/UI/Components/ErrorBoundary.js.map +1 -1
  332. package/build/dist/UI/Components/InfoCard/InfoCard.js +28 -1
  333. package/build/dist/UI/Components/InfoCard/InfoCard.js.map +1 -1
  334. package/build/dist/UI/Components/LogsViewer/components/LogTimeRangePicker.js +13 -2
  335. package/build/dist/UI/Components/LogsViewer/components/LogTimeRangePicker.js.map +1 -1
  336. package/build/dist/UI/Components/Modal/Modal.js +4 -32
  337. package/build/dist/UI/Components/Modal/Modal.js.map +1 -1
  338. package/build/dist/UI/Components/ModelFormModal/ModelFormModal.js.map +1 -1
  339. package/build/dist/UI/Components/ModelTable/BaseModelTable.js +69 -33
  340. package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
  341. package/build/dist/UI/Components/ModelTable/ColumnCustomizationModal.js +73 -32
  342. package/build/dist/UI/Components/ModelTable/ColumnCustomizationModal.js.map +1 -1
  343. package/build/dist/UI/Components/Runbook/StepTimeoutInput.js +101 -0
  344. package/build/dist/UI/Components/Runbook/StepTimeoutInput.js.map +1 -0
  345. package/build/dist/UI/Components/StatusPage/ResourceGroupSection.js +73 -0
  346. package/build/dist/UI/Components/StatusPage/ResourceGroupSection.js.map +1 -0
  347. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryTimeRangePicker.js +13 -2
  348. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryTimeRangePicker.js.map +1 -1
  349. package/build/dist/UI/Utils/DropdownAlignment.js +98 -0
  350. package/build/dist/UI/Utils/DropdownAlignment.js.map +1 -0
  351. package/build/dist/UI/Utils/TableFilterUrlState.js +48 -15
  352. package/build/dist/UI/Utils/TableFilterUrlState.js.map +1 -1
  353. package/build/dist/Utils/API.js +39 -2
  354. package/build/dist/Utils/API.js.map +1 -1
  355. package/build/dist/Utils/Monitor/MonitorSummaryProbeUtil.js +97 -0
  356. package/build/dist/Utils/Monitor/MonitorSummaryProbeUtil.js.map +1 -0
  357. package/build/dist/Utils/NetworkDiscovery/ScanTargetUtil.js +330 -0
  358. package/build/dist/Utils/NetworkDiscovery/ScanTargetUtil.js.map +1 -0
  359. package/build/dist/Utils/StatusPage/GroupNestingLayout.js +280 -0
  360. package/build/dist/Utils/StatusPage/GroupNestingLayout.js.map +1 -0
  361. package/build/dist/Utils/StatusPage/GroupTree.js +214 -0
  362. package/build/dist/Utils/StatusPage/GroupTree.js.map +1 -0
  363. package/build/dist/Utils/StatusPage/ResourceUptime.js +60 -16
  364. package/build/dist/Utils/StatusPage/ResourceUptime.js.map +1 -1
  365. package/package.json +1 -1
@@ -0,0 +1,304 @@
1
+ import MonitorProbeService from "../../../Server/Services/MonitorProbeService";
2
+ import MonitorService from "../../../Server/Services/MonitorService";
3
+ import ProbeService from "../../../Server/Services/ProbeService";
4
+ import Monitor from "../../../Models/DatabaseModels/Monitor";
5
+ import MonitorProbe from "../../../Models/DatabaseModels/MonitorProbe";
6
+ import Probe from "../../../Models/DatabaseModels/Probe";
7
+ import CreateBy from "../../../Server/Types/Database/CreateBy";
8
+ import BadDataException from "../../../Types/Exception/BadDataException";
9
+ import MonitorType from "../../../Types/Monitor/MonitorType";
10
+ import ObjectID from "../../../Types/ObjectID";
11
+ import { afterEach, beforeEach, describe, expect, it } from "@jest/globals";
12
+ import { getJestSpyOn } from "../../Spy";
13
+
14
+ /*
15
+ * Tenancy of the probe attached through the MonitorProbe CRUD path.
16
+ *
17
+ * The monitor create path already refused ids from outside the tenant, but
18
+ * POST /api/monitor-probe - what the Monitor > Probes table posts - only
19
+ * checked for duplicates and for a monitor type that supports probes, so a
20
+ * crafted request naming another project's probe was accepted. Both paths now
21
+ * share ProbeService.getProbesAttachableToProject; these tests pin the CRUD
22
+ * half of it and the shared rule itself.
23
+ */
24
+
25
+ const PROJECT_ID: ObjectID = new ObjectID(
26
+ "11111111-1111-4111-8111-111111111111",
27
+ );
28
+ const MONITOR_ID: ObjectID = new ObjectID(
29
+ "22222222-2222-4222-8222-222222222222",
30
+ );
31
+ const GLOBAL_PROBE_ID: ObjectID = new ObjectID(
32
+ "33333333-3333-4333-8333-333333333333",
33
+ );
34
+ const PROJECT_PROBE_ID: ObjectID = new ObjectID(
35
+ "44444444-4444-4444-8444-444444444444",
36
+ );
37
+ const OTHER_PROJECT_PROBE_ID: ObjectID = new ObjectID(
38
+ "55555555-5555-4555-8555-555555555555",
39
+ );
40
+
41
+ type MakeProbeFunction = (id: ObjectID) => Probe;
42
+
43
+ const makeProbe: MakeProbeFunction = (id: ObjectID): Probe => {
44
+ const probe: Probe = new Probe();
45
+ probe.id = id;
46
+ return probe;
47
+ };
48
+
49
+ type MockProbeLookupFunction = (data: {
50
+ globalProbes: Array<Probe>;
51
+ projectProbes: Array<Probe>;
52
+ }) => jest.SpyInstance<any, any>;
53
+
54
+ const mockProbeLookup: MockProbeLookupFunction = (data: {
55
+ globalProbes: Array<Probe>;
56
+ projectProbes: Array<Probe>;
57
+ }): jest.SpyInstance<any, any> => {
58
+ return getJestSpyOn(ProbeService, "findBy").mockImplementation(
59
+ async (findBy: any): Promise<Array<Probe>> => {
60
+ return findBy.query.isGlobalProbe === true
61
+ ? data.globalProbes
62
+ : data.projectProbes;
63
+ },
64
+ );
65
+ };
66
+
67
+ describe("MonitorProbeService probe tenancy", () => {
68
+ describe("onBeforeCreate", () => {
69
+ type MakeCreateByFunction = (data: {
70
+ probeId?: ObjectID | undefined;
71
+ projectId?: ObjectID | undefined;
72
+ }) => CreateBy<MonitorProbe>;
73
+
74
+ const makeCreateBy: MakeCreateByFunction = (data: {
75
+ probeId?: ObjectID | undefined;
76
+ projectId?: ObjectID | undefined;
77
+ }): CreateBy<MonitorProbe> => {
78
+ const monitorProbe: MonitorProbe = new MonitorProbe();
79
+ monitorProbe.monitorId = MONITOR_ID;
80
+
81
+ if (data.probeId) {
82
+ monitorProbe.probeId = data.probeId;
83
+ }
84
+
85
+ if (data.projectId) {
86
+ monitorProbe.projectId = data.projectId;
87
+ }
88
+
89
+ return {
90
+ data: monitorProbe,
91
+ props: {
92
+ isRoot: true,
93
+ },
94
+ } as CreateBy<MonitorProbe>;
95
+ };
96
+
97
+ type OnBeforeCreateFunction = (
98
+ createBy: CreateBy<MonitorProbe>,
99
+ ) => Promise<unknown>;
100
+
101
+ const onBeforeCreate: OnBeforeCreateFunction = (
102
+ createBy: CreateBy<MonitorProbe>,
103
+ ): Promise<unknown> => {
104
+ return (MonitorProbeService as any).onBeforeCreate(createBy);
105
+ };
106
+
107
+ beforeEach(() => {
108
+ // Not a duplicate, and a monitor type that does support probes.
109
+ getJestSpyOn(MonitorProbeService, "findOneBy").mockResolvedValue(null);
110
+
111
+ const monitor: Monitor = new Monitor();
112
+ monitor.id = MONITOR_ID;
113
+ monitor.monitorType = MonitorType.Website;
114
+
115
+ getJestSpyOn(MonitorService, "findOneById").mockResolvedValue(monitor);
116
+ });
117
+
118
+ afterEach(() => {
119
+ jest.restoreAllMocks();
120
+ });
121
+
122
+ it("rejects a probe that belongs to another project", async () => {
123
+ /*
124
+ * The probe id is posted by the browser. Owning the monitor must not be
125
+ * enough to pull a probe out of someone else's project.
126
+ */
127
+ mockProbeLookup({
128
+ globalProbes: [],
129
+ projectProbes: [],
130
+ });
131
+
132
+ await expect(
133
+ onBeforeCreate(
134
+ makeCreateBy({
135
+ probeId: OTHER_PROJECT_PROBE_ID,
136
+ projectId: PROJECT_ID,
137
+ }),
138
+ ),
139
+ ).rejects.toThrow(BadDataException);
140
+ });
141
+
142
+ it("rejects a probe id that does not exist at all", async () => {
143
+ mockProbeLookup({
144
+ globalProbes: [],
145
+ projectProbes: [],
146
+ });
147
+
148
+ await expect(
149
+ onBeforeCreate(
150
+ makeCreateBy({
151
+ probeId: new ObjectID("66666666-6666-4666-8666-666666666666"),
152
+ projectId: PROJECT_ID,
153
+ }),
154
+ ),
155
+ ).rejects.toThrow(BadDataException);
156
+ });
157
+
158
+ it("accepts a global probe", async () => {
159
+ mockProbeLookup({
160
+ globalProbes: [makeProbe(GLOBAL_PROBE_ID)],
161
+ projectProbes: [],
162
+ });
163
+
164
+ await expect(
165
+ onBeforeCreate(
166
+ makeCreateBy({
167
+ probeId: GLOBAL_PROBE_ID,
168
+ projectId: PROJECT_ID,
169
+ }),
170
+ ),
171
+ ).resolves.toBeDefined();
172
+ });
173
+
174
+ it("accepts a probe owned by this project", async () => {
175
+ mockProbeLookup({
176
+ globalProbes: [],
177
+ projectProbes: [makeProbe(PROJECT_PROBE_ID)],
178
+ });
179
+
180
+ await expect(
181
+ onBeforeCreate(
182
+ makeCreateBy({
183
+ probeId: PROJECT_PROBE_ID,
184
+ projectId: PROJECT_ID,
185
+ }),
186
+ ),
187
+ ).resolves.toBeDefined();
188
+ });
189
+
190
+ it("scopes the lookup to global probes and to this project only", async () => {
191
+ const findBySpy: jest.SpyInstance<any, any> = mockProbeLookup({
192
+ globalProbes: [makeProbe(PROJECT_PROBE_ID)],
193
+ projectProbes: [makeProbe(PROJECT_PROBE_ID)],
194
+ });
195
+
196
+ await onBeforeCreate(
197
+ makeCreateBy({
198
+ probeId: PROJECT_PROBE_ID,
199
+ projectId: PROJECT_ID,
200
+ }),
201
+ );
202
+
203
+ const calls: Array<any> = findBySpy.mock.calls.map((call: Array<any>) => {
204
+ return call[0];
205
+ });
206
+
207
+ expect(calls).toHaveLength(2);
208
+ expect(calls[0].query.isGlobalProbe).toBe(true);
209
+ expect(calls[0].query.projectId).toBeUndefined();
210
+ expect(calls[1].query.isGlobalProbe).toBe(false);
211
+ expect(calls[1].query.projectId).toEqual(PROJECT_ID);
212
+
213
+ for (const call of calls) {
214
+ expect(call.query._id).toBeDefined();
215
+ expect(call.props.isRoot).toBe(true);
216
+ }
217
+ });
218
+
219
+ it("skips the check when the create carries no probe id", async () => {
220
+ const findBySpy: jest.SpyInstance<any, any> = mockProbeLookup({
221
+ globalProbes: [],
222
+ projectProbes: [],
223
+ });
224
+
225
+ await expect(
226
+ onBeforeCreate(
227
+ makeCreateBy({
228
+ probeId: undefined,
229
+ projectId: PROJECT_ID,
230
+ }),
231
+ ),
232
+ ).resolves.toBeDefined();
233
+
234
+ expect(findBySpy).not.toHaveBeenCalled();
235
+ });
236
+ });
237
+
238
+ describe("ProbeService.getProbesAttachableToProject", () => {
239
+ afterEach(() => {
240
+ jest.restoreAllMocks();
241
+ });
242
+
243
+ it("keeps global and own-project probes and drops the rest", async () => {
244
+ mockProbeLookup({
245
+ globalProbes: [makeProbe(GLOBAL_PROBE_ID)],
246
+ projectProbes: [makeProbe(PROJECT_PROBE_ID)],
247
+ });
248
+
249
+ const probes: Array<Probe> =
250
+ await ProbeService.getProbesAttachableToProject({
251
+ probeIds: [GLOBAL_PROBE_ID, PROJECT_PROBE_ID, OTHER_PROJECT_PROBE_ID],
252
+ projectId: PROJECT_ID,
253
+ });
254
+
255
+ expect(
256
+ probes.map((probe: Probe) => {
257
+ return probe.id?.toString();
258
+ }),
259
+ ).toEqual([GLOBAL_PROBE_ID.toString(), PROJECT_PROBE_ID.toString()]);
260
+ });
261
+
262
+ it("does not query at all for an empty id list", async () => {
263
+ const findBySpy: jest.SpyInstance<any, any> = mockProbeLookup({
264
+ globalProbes: [],
265
+ projectProbes: [],
266
+ });
267
+
268
+ await expect(
269
+ ProbeService.getProbesAttachableToProject({
270
+ probeIds: [],
271
+ projectId: PROJECT_ID,
272
+ }),
273
+ ).resolves.toEqual([]);
274
+
275
+ expect(findBySpy).not.toHaveBeenCalled();
276
+ });
277
+
278
+ it("answers the single-probe question the CRUD path asks", async () => {
279
+ mockProbeLookup({
280
+ globalProbes: [],
281
+ projectProbes: [makeProbe(PROJECT_PROBE_ID)],
282
+ });
283
+
284
+ await expect(
285
+ ProbeService.isProbeAttachableToProject({
286
+ probeId: PROJECT_PROBE_ID,
287
+ projectId: PROJECT_ID,
288
+ }),
289
+ ).resolves.toBe(true);
290
+
291
+ mockProbeLookup({
292
+ globalProbes: [],
293
+ projectProbes: [],
294
+ });
295
+
296
+ await expect(
297
+ ProbeService.isProbeAttachableToProject({
298
+ probeId: OTHER_PROJECT_PROBE_ID,
299
+ projectId: PROJECT_ID,
300
+ }),
301
+ ).resolves.toBe(false);
302
+ });
303
+ });
304
+ });
@@ -0,0 +1,262 @@
1
+ import NetworkDeviceDiscoveryScanService from "../../../Server/Services/NetworkDeviceDiscoveryScanService";
2
+ import NetworkDeviceDiscoveryScan from "../../../Models/DatabaseModels/NetworkDeviceDiscoveryScan";
3
+ import BadDataException from "../../../Types/Exception/BadDataException";
4
+ import ObjectID from "../../../Types/ObjectID";
5
+ import ScanTargetUtil from "../../../Utils/NetworkDiscovery/ScanTargetUtil";
6
+ import CreateBy from "../../../Server/Types/Database/CreateBy";
7
+ import UpdateBy from "../../../Server/Types/Database/UpdateBy";
8
+ import { describe, expect, it } from "@jest/globals";
9
+
10
+ /*
11
+ * Contract under test: a discovery scan cannot be saved with a target the
12
+ * probe would later refuse to sweep. Before this validation existed, a typo
13
+ * was accepted, sat Pending until a probe claimed it, and surfaced minutes
14
+ * later as a Failed scan — octet-range notation makes that mistake much
15
+ * easier to make (a reversed range looks fine to the eye), so the check has
16
+ * to happen at write time.
17
+ */
18
+
19
+ const PROJECT_ID: ObjectID = new ObjectID(
20
+ "22222222-2222-4222-8222-222222222222",
21
+ );
22
+ const PROBE_ID: ObjectID = new ObjectID("11111111-1111-4111-8111-111111111111");
23
+
24
+ /*
25
+ * `cidr` is typed unknown, not string: this hook runs before the model's own
26
+ * type and length checks, and BaseAPI assigns ShortText columns straight from
27
+ * the request JSON — so a client that sends a number or an object really does
28
+ * reach it with that value.
29
+ */
30
+ function makeCreateBy(cidr?: unknown): CreateBy<NetworkDeviceDiscoveryScan> {
31
+ const scan: NetworkDeviceDiscoveryScan = new NetworkDeviceDiscoveryScan();
32
+ scan.projectId = PROJECT_ID;
33
+ scan.probeId = PROBE_ID;
34
+ if (cidr !== undefined) {
35
+ (scan as unknown as Record<string, unknown>)["cidr"] = cidr;
36
+ }
37
+ return {
38
+ data: scan,
39
+ props: { isRoot: true },
40
+ };
41
+ }
42
+
43
+ function makeUpdateBy(
44
+ data: Record<string, unknown>,
45
+ ): UpdateBy<NetworkDeviceDiscoveryScan> {
46
+ return {
47
+ query: { projectId: PROJECT_ID },
48
+ data: data,
49
+ props: { isRoot: true },
50
+ limit: 1,
51
+ skip: 0,
52
+ } as unknown as UpdateBy<NetworkDeviceDiscoveryScan>;
53
+ }
54
+
55
+ type OnBeforeCreateFunction = (
56
+ createBy: CreateBy<NetworkDeviceDiscoveryScan>,
57
+ ) => Promise<unknown>;
58
+
59
+ type OnBeforeUpdateFunction = (
60
+ updateBy: UpdateBy<NetworkDeviceDiscoveryScan>,
61
+ ) => Promise<unknown>;
62
+
63
+ const onBeforeCreate: OnBeforeCreateFunction = (
64
+ createBy: CreateBy<NetworkDeviceDiscoveryScan>,
65
+ ): Promise<unknown> => {
66
+ return (NetworkDeviceDiscoveryScanService as any).onBeforeCreate(createBy);
67
+ };
68
+
69
+ const onBeforeUpdate: OnBeforeUpdateFunction = (
70
+ updateBy: UpdateBy<NetworkDeviceDiscoveryScan>,
71
+ ): Promise<unknown> => {
72
+ return (NetworkDeviceDiscoveryScanService as any).onBeforeUpdate(updateBy);
73
+ };
74
+
75
+ describe("NetworkDeviceDiscoveryScanService.onBeforeCreate", () => {
76
+ it("accepts a CIDR target", async () => {
77
+ await expect(
78
+ onBeforeCreate(makeCreateBy("192.168.1.0/24")),
79
+ ).resolves.toBeDefined();
80
+ });
81
+
82
+ it("accepts an octet-range target", async () => {
83
+ await expect(
84
+ onBeforeCreate(makeCreateBy("10.16-22.0-255.51-66")),
85
+ ).resolves.toBeDefined();
86
+ });
87
+
88
+ it("accepts a single-host target", async () => {
89
+ await expect(
90
+ onBeforeCreate(makeCreateBy("10.0.0.5")),
91
+ ).resolves.toBeDefined();
92
+ });
93
+
94
+ it("trims surrounding whitespace before validating", async () => {
95
+ await expect(
96
+ onBeforeCreate(makeCreateBy(" 10.16-22.0-255.51-66 ")),
97
+ ).resolves.toBeDefined();
98
+ });
99
+
100
+ it("rejects a missing target", async () => {
101
+ await expect(onBeforeCreate(makeCreateBy())).rejects.toThrow(
102
+ BadDataException,
103
+ );
104
+ });
105
+
106
+ it("rejects an empty or whitespace-only target", async () => {
107
+ await expect(onBeforeCreate(makeCreateBy(""))).rejects.toThrow(
108
+ BadDataException,
109
+ );
110
+ await expect(onBeforeCreate(makeCreateBy(" "))).rejects.toThrow(
111
+ BadDataException,
112
+ );
113
+ });
114
+
115
+ it("rejects a malformed CIDR", async () => {
116
+ await expect(onBeforeCreate(makeCreateBy("10.0.0.0/33"))).rejects.toThrow(
117
+ /between \/0 and \/32/,
118
+ );
119
+ await expect(onBeforeCreate(makeCreateBy("not-a-target"))).rejects.toThrow(
120
+ BadDataException,
121
+ );
122
+ });
123
+
124
+ it("rejects a reversed octet range with a message naming the fix", async () => {
125
+ await expect(
126
+ onBeforeCreate(makeCreateBy("10.22-16.0.1-20")),
127
+ ).rejects.toThrow(/reversed/);
128
+ });
129
+
130
+ it("rejects an out-of-range octet", async () => {
131
+ await expect(onBeforeCreate(makeCreateBy("10.0.0.256"))).rejects.toThrow(
132
+ /between 0 and 255/,
133
+ );
134
+ });
135
+
136
+ /*
137
+ * The size ceiling belongs on the form, not on a scan result: rejecting at
138
+ * write time is the difference between an inline error and a probe being
139
+ * handed a sweep it refuses minutes later.
140
+ */
141
+ it("rejects a target above the scan-size ceiling", async () => {
142
+ await expect(onBeforeCreate(makeCreateBy("10.0.0.0/8"))).rejects.toThrow(
143
+ /exceeding the/,
144
+ );
145
+ await expect(
146
+ onBeforeCreate(makeCreateBy("10.0-255.0-255.1-10")),
147
+ ).rejects.toThrow(/exceeding the/);
148
+ });
149
+
150
+ it("accepts a target exactly at the ceiling", async () => {
151
+ const atLimit: string = "10.0.0-127.0-255";
152
+ expect(ScanTargetUtil.countHosts(atLimit)).toBe(
153
+ ScanTargetUtil.MAX_SCAN_HOSTS,
154
+ );
155
+ await expect(onBeforeCreate(makeCreateBy(atLimit))).resolves.toBeDefined();
156
+ });
157
+
158
+ /*
159
+ * This hook is the FIRST thing to touch the raw request value:
160
+ * DatabaseService.create runs it before checkRequiredFields, before the
161
+ * column type/length checks and before the create-permission check, and
162
+ * BaseAPI assigns a ShortText column straight from the JSON body. So a
163
+ * client sending `"cidr": 42` reaches here with the number 42. Normalizing
164
+ * the value in the hook (`(target || "").trim()`) would throw a TypeError
165
+ * on every truthy non-string and turn the intended 400 into a 500.
166
+ */
167
+ it("rejects a non-string target with BadDataException, not a TypeError", async () => {
168
+ for (const badValue of [
169
+ 42,
170
+ true,
171
+ {},
172
+ [],
173
+ ["10.0.0.0/24"],
174
+ { value: "10.0.0.0/24" },
175
+ 0,
176
+ null,
177
+ ]) {
178
+ await expect(onBeforeCreate(makeCreateBy(badValue))).rejects.toThrow(
179
+ BadDataException,
180
+ );
181
+ }
182
+ });
183
+
184
+ it("rejects a non-string target on update too", async () => {
185
+ await expect(onBeforeUpdate(makeUpdateBy({ cidr: 42 }))).rejects.toThrow(
186
+ BadDataException,
187
+ );
188
+ await expect(onBeforeUpdate(makeUpdateBy({ cidr: {} }))).rejects.toThrow(
189
+ BadDataException,
190
+ );
191
+ });
192
+
193
+ /*
194
+ * The error quotes the target back, so an unbounded target would be
195
+ * amplified into the exception, the logs and the response body — and this
196
+ * hook runs before the column's 100-character cap would have stopped it.
197
+ */
198
+ it("rejects an over-long target without echoing it", async () => {
199
+ const huge: string = `1.2.3.${"9".repeat(100000)}`;
200
+
201
+ await expect(onBeforeCreate(makeCreateBy(huge))).rejects.toThrow(
202
+ /cannot be longer than/,
203
+ );
204
+
205
+ let message: string = "";
206
+ try {
207
+ await onBeforeCreate(makeCreateBy(huge));
208
+ } catch (err) {
209
+ message = (err as Error).message;
210
+ }
211
+ expect(message.length).toBeLessThan(400);
212
+ });
213
+
214
+ it("returns the createBy unchanged so the write proceeds", async () => {
215
+ const createBy: CreateBy<NetworkDeviceDiscoveryScan> =
216
+ makeCreateBy("192.168.1.0/24");
217
+ const result: any = await onBeforeCreate(createBy);
218
+ expect(result.createBy).toBe(createBy);
219
+ expect(result.createBy.data.cidr).toBe("192.168.1.0/24");
220
+ });
221
+ });
222
+
223
+ describe("NetworkDeviceDiscoveryScanService.onBeforeUpdate", () => {
224
+ /*
225
+ * Every run-state write (claiming a scan, reporting a result, re-queueing a
226
+ * recurring one) is an update that does NOT carry the target column. Those
227
+ * must pass straight through — validating a column that is not being written
228
+ * would break the entire scan lifecycle.
229
+ */
230
+ it("ignores updates that do not touch the target", async () => {
231
+ await expect(
232
+ onBeforeUpdate(
233
+ makeUpdateBy({ status: "In Progress", startedAt: new Date(0) }),
234
+ ),
235
+ ).resolves.toBeDefined();
236
+ });
237
+
238
+ it("ignores an update with no data at all", async () => {
239
+ await expect(onBeforeUpdate(makeUpdateBy({}))).resolves.toBeDefined();
240
+ });
241
+
242
+ it("validates a target carried by an update", async () => {
243
+ await expect(
244
+ onBeforeUpdate(makeUpdateBy({ cidr: "10.22-16.0.1" })),
245
+ ).rejects.toThrow(BadDataException);
246
+ });
247
+
248
+ it("accepts a valid target carried by an update", async () => {
249
+ await expect(
250
+ onBeforeUpdate(makeUpdateBy({ cidr: "10.16-22.0-255.51-66" })),
251
+ ).resolves.toBeDefined();
252
+ });
253
+
254
+ it("rejects an update that clears the target", async () => {
255
+ await expect(onBeforeUpdate(makeUpdateBy({ cidr: null }))).rejects.toThrow(
256
+ BadDataException,
257
+ );
258
+ await expect(onBeforeUpdate(makeUpdateBy({ cidr: "" }))).rejects.toThrow(
259
+ BadDataException,
260
+ );
261
+ });
262
+ });