@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
@@ -315,3 +315,167 @@ describe("CommonAPI.assertAuthenticatedProjectMember", () => {
315
315
  });
316
316
  });
317
317
  });
318
+
319
+ /*
320
+ * Tests for CommonAPI.assertResourceBelongsToProject — the companion guard
321
+ * for custom routes whose path carries a resource id.
322
+ * assertAuthenticatedProjectMember only proves the caller belongs to the
323
+ * project it claimed in the `tenantid` header; without this second check a
324
+ * member of project A could hand the route project B's resource id and have
325
+ * it acted on as root.
326
+ */
327
+ describe("CommonAPI.assertResourceBelongsToProject", () => {
328
+ test("does not throw when the resource belongs to the authorized project", () => {
329
+ const projectId: ObjectID = ObjectID.generate();
330
+
331
+ expect(() => {
332
+ CommonAPI.assertResourceBelongsToProject({
333
+ resourceProjectId: projectId,
334
+ projectId: projectId,
335
+ });
336
+ }).not.toThrow();
337
+ });
338
+
339
+ test("compares by string value, not by ObjectID instance", () => {
340
+ const projectIdString: string = ObjectID.generate().toString();
341
+
342
+ expect(() => {
343
+ CommonAPI.assertResourceBelongsToProject({
344
+ resourceProjectId: new ObjectID(projectIdString),
345
+ projectId: new ObjectID(projectIdString),
346
+ });
347
+ }).not.toThrow();
348
+ });
349
+
350
+ test("throws NotAuthorizedException when the resource belongs to another project", () => {
351
+ const thrown: unknown = captureThrown(() => {
352
+ CommonAPI.assertResourceBelongsToProject({
353
+ resourceProjectId: ObjectID.generate(),
354
+ projectId: ObjectID.generate(),
355
+ });
356
+ });
357
+
358
+ expect(thrown).toBeInstanceOf(NotAuthorizedException);
359
+ expect((thrown as Exception).message).toBe(
360
+ "You are not authorized to access this project's data.",
361
+ );
362
+ });
363
+
364
+ /*
365
+ * A row that was not found reaches the guard as undefined. It must be
366
+ * rejected exactly like a cross-project row, so the endpoint cannot be
367
+ * used to tell "id exists in another project" apart from "id does not
368
+ * exist".
369
+ */
370
+ test("throws NotAuthorizedException when the resource was not found", () => {
371
+ const thrown: unknown = captureThrown(() => {
372
+ CommonAPI.assertResourceBelongsToProject({
373
+ resourceProjectId: undefined,
374
+ projectId: ObjectID.generate(),
375
+ });
376
+ });
377
+
378
+ expect(thrown).toBeInstanceOf(NotAuthorizedException);
379
+ expect((thrown as Exception).message).toBe(
380
+ "You are not authorized to access this project's data.",
381
+ );
382
+ });
383
+
384
+ test("throws NotAuthorizedException when the resource carries a null projectId", () => {
385
+ expect(() => {
386
+ CommonAPI.assertResourceBelongsToProject({
387
+ resourceProjectId: null,
388
+ projectId: ObjectID.generate(),
389
+ });
390
+ }).toThrow(NotAuthorizedException);
391
+ });
392
+ });
393
+
394
+ /*
395
+ * Tests for CommonAPI.assertTenantScoped — the lighter guard for custom
396
+ * endpoints whose path carries only a resource id, so the project can only
397
+ * come from the `tenantid` header. Without it the request still reaches the
398
+ * handler, just with no tenant permissions, and the eventual tenant-scoped
399
+ * read fails as "You do not have permissions to read <model>" — a message
400
+ * that sends project owners hunting for a role they already hold. The guard
401
+ * exists to surface the real cause (a missing header) instead.
402
+ */
403
+ describe("CommonAPI.assertTenantScoped", () => {
404
+ test("throws BadDataException naming the tenantid header when tenantId is missing", () => {
405
+ const props: DatabaseCommonInteractionProps = buildProps({
406
+ tenantId: undefined,
407
+ userId: ObjectID.generate(),
408
+ });
409
+
410
+ const thrown: unknown = captureThrown(() => {
411
+ CommonAPI.assertTenantScoped(props);
412
+ });
413
+
414
+ expect(thrown).toBeInstanceOf(BadDataException);
415
+ expect((thrown as Exception).message).toContain("Project ID is required");
416
+ expect((thrown as Exception).message).toContain("tenantid");
417
+ });
418
+
419
+ test("the message points at the header rather than at permissions", () => {
420
+ const thrown: unknown = captureThrown(() => {
421
+ CommonAPI.assertTenantScoped({});
422
+ });
423
+
424
+ /*
425
+ * The whole point of the guard: whatever it says must not look like the
426
+ * permissions error it replaces.
427
+ */
428
+ expect((thrown as Exception).message).toContain("tenantid");
429
+ expect((thrown as Exception).message).not.toContain("permission");
430
+ });
431
+
432
+ test("returns the tenant id when the request is project scoped", () => {
433
+ const projectId: ObjectID = ObjectID.generate();
434
+ const props: DatabaseCommonInteractionProps = buildProps({
435
+ tenantId: projectId,
436
+ userId: ObjectID.generate(),
437
+ });
438
+
439
+ expect(CommonAPI.assertTenantScoped(props)).toBe(projectId);
440
+ });
441
+
442
+ /*
443
+ * API-key callers are authenticated by ProjectMiddleware, which sets
444
+ * userType/tenantId and the tenant permission map but never userId. This
445
+ * guard must not lock them out — that is what separates it from
446
+ * assertAuthenticatedProjectMember.
447
+ */
448
+ test("accepts an API-key caller that has a tenant but no userId", () => {
449
+ const projectId: ObjectID = ObjectID.generate();
450
+ const permissions: Dictionary<UserTenantAccessPermission> = {};
451
+ permissions[projectId.toString()] = buildTenantPermission(projectId);
452
+
453
+ const props: DatabaseCommonInteractionProps = buildProps({
454
+ tenantId: projectId,
455
+ userId: undefined,
456
+ userTenantAccessPermission: permissions,
457
+ });
458
+
459
+ expect(() => {
460
+ CommonAPI.assertTenantScoped(props);
461
+ }).not.toThrow();
462
+ });
463
+
464
+ test("does not require membership — that stays with the tenant-scoped read", () => {
465
+ /*
466
+ * assertTenantScoped is a diagnostic for a missing header, not an
467
+ * authorization check. A caller who sends a tenant id for a project they
468
+ * are not a member of passes here and is rejected by the read itself, so
469
+ * adding this guard cannot loosen or tighten access.
470
+ */
471
+ const props: DatabaseCommonInteractionProps = buildProps({
472
+ tenantId: ObjectID.generate(),
473
+ userId: undefined,
474
+ userTenantAccessPermission: undefined,
475
+ });
476
+
477
+ expect(() => {
478
+ CommonAPI.assertTenantScoped(props);
479
+ }).not.toThrow();
480
+ });
481
+ });
@@ -8,9 +8,14 @@ import {
8
8
  import Response from "../../../Server/Utils/Response";
9
9
  import { mockRouter } from "./Helpers";
10
10
  import { describe, expect, it } from "@jest/globals";
11
- import LIMIT_MAX from "../../../Types/Database/LimitMax";
11
+ import MultiSearch from "../../../Types/BaseDatabase/MultiSearch";
12
+ import { DEFAULT_LIMIT } from "../../../Types/Database/LimitMax";
13
+ import BadDataException from "../../../Types/Exception/BadDataException";
14
+ import BadRequestException from "../../../Types/Exception/BadRequestException";
15
+ import { JSONObject } from "../../../Types/JSON";
12
16
  import PositiveNumber from "../../../Types/PositiveNumber";
13
17
  import Probe from "../../../Models/DatabaseModels/Probe";
18
+ import SortOrder from "../../../Types/BaseDatabase/SortOrder";
14
19
 
15
20
  jest.mock("../../../Server/Utils/Express", () => {
16
21
  return {
@@ -37,77 +42,441 @@ jest.mock("../../../Server/Utils/Response", () => {
37
42
 
38
43
  jest.mock("../../../Server/Services/ProbeService");
39
44
 
45
+ type RequestOverrides = {
46
+ body?: JSONObject | undefined;
47
+ query?: JSONObject | undefined;
48
+ };
49
+
40
50
  describe("ProbeAPI", () => {
41
- let mockRequest: ExpressRequest;
42
51
  let mockResponse: ExpressResponse;
43
52
  let nextFunction: NextFunction;
44
53
 
54
+ const buildRequest: (overrides?: RequestOverrides) => ExpressRequest = (
55
+ overrides: RequestOverrides = {},
56
+ ): ExpressRequest => {
57
+ return {
58
+ body: overrides.body || {},
59
+ query: overrides.query || {},
60
+ } as unknown as ExpressRequest;
61
+ };
62
+
63
+ type CallGlobalProbesFunction = (
64
+ overrides?: RequestOverrides,
65
+ ) => Promise<ExpressRequest>;
66
+
67
+ const callGlobalProbes: CallGlobalProbesFunction = async (
68
+ overrides: RequestOverrides = {},
69
+ ): Promise<ExpressRequest> => {
70
+ const request: ExpressRequest = buildRequest(overrides);
71
+
72
+ await mockRouter
73
+ .match("post", "/probe/global-probes")
74
+ .handlerFunction(request, mockResponse, nextFunction);
75
+
76
+ return request;
77
+ };
78
+
45
79
  beforeEach(() => {
46
80
  new ProbeAPI();
47
- mockRequest = {} as ExpressRequest;
48
81
  mockResponse = {
49
82
  send: jest.fn(),
50
83
  json: jest.fn(),
51
84
  status: jest.fn().mockReturnThis(),
52
85
  } as unknown as ExpressResponse;
53
86
  nextFunction = jest.fn();
87
+
88
+ ProbeService.findBy = jest.fn().mockResolvedValue([]);
89
+ ProbeService.countBy = jest.fn().mockResolvedValue(new PositiveNumber(0));
54
90
  });
55
91
 
56
- it("should correctly handle global probes request", async () => {
57
- // eslint-disable-next-line @typescript-eslint/typedef
58
- const mockProbes = [{ id: "probe" }];
59
- ProbeService.findBy = jest.fn().mockResolvedValue(mockProbes);
60
- await mockRouter
61
- .match("post", "/probe/global-probes")
62
- .handlerFunction(mockRequest, mockResponse, nextFunction);
63
-
64
- expect(ProbeService.findBy).toHaveBeenCalledWith({
65
- query: {
66
- isGlobalProbe: true,
67
- },
68
- select: {
69
- name: true,
70
- description: true,
71
- connectionStatus: true,
72
- lastAlive: true,
73
- iconFileId: true,
74
- /*
75
- * The monitor create form pre-selects the probes that auto-enable on
76
- * new monitors, and global probes are not project rows - this endpoint
77
- * is the only place the browser can learn the flag for them.
78
- */
79
- shouldAutoEnableProbeOnNewMonitors: true,
80
- },
81
- props: {
82
- isRoot: true,
83
- },
84
- skip: 0,
85
- limit: LIMIT_MAX,
86
- });
87
-
88
- const response: jest.SpyInstance = jest.spyOn(
89
- Response,
90
- "sendEntityArrayResponse",
91
- );
92
- expect(response).toHaveBeenCalledWith(
93
- mockRequest,
94
- mockResponse,
95
- mockProbes,
96
- expect.any(PositiveNumber),
97
- Probe,
98
- );
92
+ afterEach(() => {
93
+ jest.restoreAllMocks();
94
+ });
95
+
96
+ describe("defaults", () => {
97
+ it("should read the full select list when the caller asks for no fields", async () => {
98
+ const mockProbes: Array<Probe> = [{ id: "probe" } as unknown as Probe];
99
+ ProbeService.findBy = jest.fn().mockResolvedValue(mockProbes);
100
+
101
+ const request: ExpressRequest = await callGlobalProbes();
102
+
103
+ expect(ProbeService.findBy).toHaveBeenCalledWith({
104
+ query: {
105
+ isGlobalProbe: true,
106
+ },
107
+ select: {
108
+ name: true,
109
+ description: true,
110
+ lastAlive: true,
111
+ iconFileId: true,
112
+ connectionStatus: true,
113
+ shouldAutoEnableProbeOnNewMonitors: true,
114
+ },
115
+ sort: {},
116
+ props: {
117
+ isRoot: true,
118
+ },
119
+ skip: new PositiveNumber(0),
120
+ limit: new PositiveNumber(DEFAULT_LIMIT),
121
+ });
122
+
123
+ const response: jest.SpyInstance = jest.spyOn(
124
+ Response,
125
+ "sendEntityArrayResponse",
126
+ );
127
+ expect(response).toHaveBeenCalledWith(
128
+ request,
129
+ mockResponse,
130
+ mockProbes,
131
+ expect.any(PositiveNumber),
132
+ Probe,
133
+ );
134
+ });
135
+ });
136
+
137
+ describe("query", () => {
138
+ it("should pass the caller's query through alongside isGlobalProbe", async () => {
139
+ await callGlobalProbes({
140
+ body: {
141
+ query: {
142
+ name: "probe-1",
143
+ },
144
+ },
145
+ });
146
+
147
+ expect(ProbeService.findBy).toHaveBeenCalledWith(
148
+ expect.objectContaining({
149
+ query: {
150
+ name: "probe-1",
151
+ isGlobalProbe: true,
152
+ },
153
+ }),
154
+ );
155
+ });
156
+
157
+ it("should not let the caller widen the read past global probes", async () => {
158
+ await callGlobalProbes({
159
+ body: {
160
+ query: {
161
+ isGlobalProbe: false,
162
+ },
163
+ },
164
+ });
165
+
166
+ expect(ProbeService.findBy).toHaveBeenCalledWith(
167
+ expect.objectContaining({
168
+ query: {
169
+ isGlobalProbe: true,
170
+ },
171
+ }),
172
+ );
173
+ });
174
+
175
+ it("should reject a filter on a field outside the select list", async () => {
176
+ await callGlobalProbes({
177
+ body: {
178
+ query: {
179
+ key: "secret-probe-key",
180
+ },
181
+ },
182
+ });
183
+
184
+ expect(ProbeService.findBy).not.toHaveBeenCalled();
185
+ expect(nextFunction).toHaveBeenCalledWith(expect.any(BadDataException));
186
+ });
187
+
188
+ it("should allow a multi field search over allowed fields", async () => {
189
+ const search: MultiSearch = new MultiSearch({
190
+ fields: ["name", "description"],
191
+ value: "probe",
192
+ });
193
+
194
+ await callGlobalProbes({
195
+ body: {
196
+ query: {
197
+ _multiFieldSearch: search.toJSON(),
198
+ },
199
+ },
200
+ });
201
+
202
+ expect(nextFunction).not.toHaveBeenCalled();
203
+ expect(ProbeService.findBy).toHaveBeenCalledWith(
204
+ expect.objectContaining({
205
+ query: expect.objectContaining({
206
+ _multiFieldSearch: expect.any(MultiSearch),
207
+ isGlobalProbe: true,
208
+ }),
209
+ }),
210
+ );
211
+ });
212
+
213
+ it("should reject a multi field search that reaches a field outside the select list", async () => {
214
+ const search: MultiSearch = new MultiSearch({
215
+ fields: ["name", "key"],
216
+ value: "a",
217
+ });
218
+
219
+ await callGlobalProbes({
220
+ body: {
221
+ query: {
222
+ _multiFieldSearch: search.toJSON(),
223
+ },
224
+ },
225
+ });
226
+
227
+ expect(ProbeService.findBy).not.toHaveBeenCalled();
228
+ expect(nextFunction).toHaveBeenCalledWith(expect.any(BadDataException));
229
+ });
230
+ });
231
+
232
+ describe("select", () => {
233
+ it("should honour the caller's select", async () => {
234
+ await callGlobalProbes({
235
+ body: {
236
+ select: {
237
+ name: true,
238
+ shouldAutoEnableProbeOnNewMonitors: true,
239
+ },
240
+ },
241
+ });
242
+
243
+ expect(ProbeService.findBy).toHaveBeenCalledWith(
244
+ expect.objectContaining({
245
+ select: {
246
+ name: true,
247
+ shouldAutoEnableProbeOnNewMonitors: true,
248
+ },
249
+ }),
250
+ );
251
+ });
252
+
253
+ it("should drop selected fields outside the select list", async () => {
254
+ await callGlobalProbes({
255
+ body: {
256
+ select: {
257
+ name: true,
258
+ key: true,
259
+ slug: true,
260
+ },
261
+ },
262
+ });
263
+
264
+ expect(ProbeService.findBy).toHaveBeenCalledWith(
265
+ expect.objectContaining({
266
+ select: {
267
+ name: true,
268
+ },
269
+ }),
270
+ );
271
+ });
272
+
273
+ it("should not let an allowed field be turned into a relation select", async () => {
274
+ await callGlobalProbes({
275
+ body: {
276
+ select: {
277
+ name: {
278
+ key: true,
279
+ },
280
+ },
281
+ },
282
+ });
283
+
284
+ expect(ProbeService.findBy).toHaveBeenCalledWith(
285
+ expect.objectContaining({
286
+ select: {
287
+ name: true,
288
+ },
289
+ }),
290
+ );
291
+ });
292
+
293
+ it("should fall back to the default select when nothing selectable is asked for", async () => {
294
+ await callGlobalProbes({
295
+ body: {
296
+ select: {
297
+ key: true,
298
+ },
299
+ },
300
+ });
301
+
302
+ expect(ProbeService.findBy).toHaveBeenCalledWith(
303
+ expect.objectContaining({
304
+ select: {
305
+ name: true,
306
+ description: true,
307
+ lastAlive: true,
308
+ iconFileId: true,
309
+ connectionStatus: true,
310
+ shouldAutoEnableProbeOnNewMonitors: true,
311
+ },
312
+ }),
313
+ );
314
+ });
315
+ });
316
+
317
+ describe("sort", () => {
318
+ it("should honour the caller's sort", async () => {
319
+ await callGlobalProbes({
320
+ body: {
321
+ sort: {
322
+ name: SortOrder.Descending,
323
+ },
324
+ },
325
+ });
326
+
327
+ expect(ProbeService.findBy).toHaveBeenCalledWith(
328
+ expect.objectContaining({
329
+ sort: {
330
+ name: SortOrder.Descending,
331
+ },
332
+ }),
333
+ );
334
+ });
335
+
336
+ it("should reject a sort on a field outside the select list", async () => {
337
+ await callGlobalProbes({
338
+ body: {
339
+ sort: {
340
+ key: SortOrder.Ascending,
341
+ },
342
+ },
343
+ });
344
+
345
+ expect(ProbeService.findBy).not.toHaveBeenCalled();
346
+ expect(nextFunction).toHaveBeenCalledWith(expect.any(BadDataException));
347
+ });
348
+ });
349
+
350
+ describe("pagination", () => {
351
+ it("should read skip and limit from the query string", async () => {
352
+ await callGlobalProbes({
353
+ query: {
354
+ skip: "20",
355
+ limit: "5",
356
+ },
357
+ });
358
+
359
+ expect(ProbeService.findBy).toHaveBeenCalledWith(
360
+ expect.objectContaining({
361
+ skip: new PositiveNumber(20),
362
+ limit: new PositiveNumber(5),
363
+ }),
364
+ );
365
+ });
366
+
367
+ it("should read skip and limit from the body", async () => {
368
+ await callGlobalProbes({
369
+ body: {
370
+ skip: 10,
371
+ limit: 25,
372
+ },
373
+ });
374
+
375
+ expect(ProbeService.findBy).toHaveBeenCalledWith(
376
+ expect.objectContaining({
377
+ skip: new PositiveNumber(10),
378
+ limit: new PositiveNumber(25),
379
+ }),
380
+ );
381
+ });
382
+
383
+ it("should prefer the query string over the body", async () => {
384
+ await callGlobalProbes({
385
+ body: {
386
+ skip: 10,
387
+ limit: 25,
388
+ },
389
+ query: {
390
+ skip: "30",
391
+ limit: "40",
392
+ },
393
+ });
394
+
395
+ expect(ProbeService.findBy).toHaveBeenCalledWith(
396
+ expect.objectContaining({
397
+ skip: new PositiveNumber(30),
398
+ limit: new PositiveNumber(40),
399
+ }),
400
+ );
401
+ });
402
+
403
+ it("should reject a limit above the per project maximum", async () => {
404
+ await callGlobalProbes({
405
+ body: {
406
+ limit: 10001,
407
+ },
408
+ });
409
+
410
+ expect(ProbeService.findBy).not.toHaveBeenCalled();
411
+ expect(nextFunction).toHaveBeenCalledWith(
412
+ expect.any(BadRequestException),
413
+ );
414
+ });
415
+ });
416
+
417
+ describe("count", () => {
418
+ it("should return the real count rather than the size of the page", async () => {
419
+ const mockProbes: Array<Probe> = [{ id: "probe" } as unknown as Probe];
420
+ ProbeService.findBy = jest.fn().mockResolvedValue(mockProbes);
421
+ ProbeService.countBy = jest
422
+ .fn()
423
+ .mockResolvedValue(new PositiveNumber(137));
424
+
425
+ const request: ExpressRequest = await callGlobalProbes({
426
+ query: {
427
+ limit: "1",
428
+ },
429
+ });
430
+
431
+ expect(ProbeService.countBy).toHaveBeenCalledWith({
432
+ query: {
433
+ isGlobalProbe: true,
434
+ },
435
+ props: {
436
+ isRoot: true,
437
+ },
438
+ });
439
+
440
+ const response: jest.SpyInstance = jest.spyOn(
441
+ Response,
442
+ "sendEntityArrayResponse",
443
+ );
444
+ expect(response).toHaveBeenCalledWith(
445
+ request,
446
+ mockResponse,
447
+ mockProbes,
448
+ new PositiveNumber(137),
449
+ Probe,
450
+ );
451
+ });
452
+
453
+ it("should count against the same filtered query the list used", async () => {
454
+ await callGlobalProbes({
455
+ body: {
456
+ query: {
457
+ name: "probe-1",
458
+ },
459
+ },
460
+ });
461
+
462
+ expect(ProbeService.countBy).toHaveBeenCalledWith({
463
+ query: {
464
+ name: "probe-1",
465
+ isGlobalProbe: true,
466
+ },
467
+ props: {
468
+ isRoot: true,
469
+ },
470
+ });
471
+ });
99
472
  });
100
473
 
101
474
  it("should call next with an error if findBy throws", async () => {
102
475
  const testError: Error = new Error("Test error");
103
476
  ProbeService.findBy = jest.fn().mockRejectedValue(testError);
104
- await mockRouter
105
- .match("post", "/probe/global-probes")
106
- .handlerFunction(mockRequest, mockResponse, nextFunction);
107
- expect(nextFunction).toHaveBeenCalledWith(testError);
108
- });
109
477
 
110
- afterEach(() => {
111
- jest.restoreAllMocks();
478
+ await callGlobalProbes();
479
+
480
+ expect(nextFunction).toHaveBeenCalledWith(testError);
112
481
  });
113
482
  });