@oneuptime/common 12.0.9 → 12.0.11

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 (262) hide show
  1. package/Models/DatabaseModels/NetworkDevice.ts +44 -0
  2. package/Models/DatabaseModels/NetworkDeviceLink.ts +116 -0
  3. package/Models/DatabaseModels/RunnerJob.ts +17 -2
  4. package/Server/API/LlmProviderAPI.ts +8 -0
  5. package/Server/Infrastructure/Postgres/SchemaMigrations/1787400000000-AddDeviceRoleAndDeclaredLinkParent.ts +52 -0
  6. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +2 -0
  7. package/Server/Services/NetworkDeviceLabelRuleEngineService.ts +240 -0
  8. package/Server/Services/NetworkDeviceLinkService.ts +338 -2
  9. package/Server/Services/NetworkDeviceService.ts +265 -12
  10. package/Server/Services/RunnerJobService.ts +24 -1
  11. package/Server/Types/Billing/MeteredPlan/AllMeteredPlans.ts +19 -5
  12. package/Server/Types/Database/JSONColumnQuery.ts +42 -4
  13. package/Server/Utils/LLM/LLMService.ts +108 -19
  14. package/Server/Utils/Monitor/MonitorAlert.ts +22 -115
  15. package/Server/Utils/Monitor/MonitorIncident.ts +7 -337
  16. package/Server/Utils/Monitor/MonitorMaintenanceSuppression.ts +27 -2
  17. package/Server/Utils/Monitor/SeriesResourceLabels.ts +32 -0
  18. package/Server/Utils/Monitor/SeriesResourceLinker.ts +469 -0
  19. package/Server/Utils/SSRFProtection.ts +5 -4
  20. package/Server/Utils/Telemetry/InventoryEntityRegistry.ts +186 -38
  21. package/Tests/App/AdminDashboard/AdminUsersBulkAddToProject.test.tsx +955 -0
  22. package/Tests/App/AdminDashboard/BulkAddUsersToProject.test.ts +778 -0
  23. package/Tests/App/AdminDashboard/BulkAddUsersToProjectModal.test.tsx +1051 -0
  24. package/Tests/App/Dashboard/AdminNotificationRulesPage.test.tsx +420 -112
  25. package/Tests/App/Dashboard/OnCallReadinessSurfaces.test.tsx +81 -6
  26. package/Tests/App/Dashboard/PayAsYouGoConsentGate.test.tsx +543 -0
  27. package/Tests/App/Dashboard/PayAsYouGoFreePlan.test.ts +125 -0
  28. package/Tests/App/Dashboard/PayAsYouGoNotices.test.tsx +612 -0
  29. package/Tests/App/Dashboard/SloWidgetChartRendering.test.tsx +536 -0
  30. package/Tests/App/Dashboard/UserElementEmail.test.tsx +447 -0
  31. package/Tests/App/Dashboard/UserEmailCallSites.test.tsx +284 -0
  32. package/Tests/Models/AnalyticsModels/CommonModel.test.ts +312 -0
  33. package/Tests/Server/Infrastructure/Postgres/DeviceRoleAndDeclaredLinkParentMigration.test.ts +250 -0
  34. package/Tests/Server/Infrastructure/Postgres/EpisodeMemberNotifyIndexesMigration.test.ts +46 -18
  35. package/Tests/Server/Services/NetworkDeviceLabelRuleRun.test.ts +618 -0
  36. package/Tests/Server/Services/NetworkDeviceLinkParentValidation.test.ts +1043 -0
  37. package/Tests/Server/Services/NetworkSiteAssignmentRuleRun.test.ts +706 -0
  38. package/Tests/Server/Services/RunnerJobEnqueue.test.ts +412 -0
  39. package/Tests/Server/Types/Billing/PayAsYouGoMeteredPricing.test.ts +125 -0
  40. package/Tests/Server/Types/Database/JSONColumnQuery.test.ts +508 -0
  41. package/Tests/Server/Utils/AI/LLMServiceRequestPolicy.test.ts +2 -2
  42. package/Tests/Server/Utils/AI/LLMServiceRetryPolicy.test.ts +450 -0
  43. package/Tests/Server/Utils/Monitor/MonitorAlertResourceLinking.test.ts +556 -0
  44. package/Tests/Server/Utils/Monitor/MonitorIncidentResourceLinking.test.ts +547 -0
  45. package/Tests/Server/Utils/Monitor/MonitorMaintenanceSuppression.test.ts +30 -0
  46. package/Tests/Server/Utils/Monitor/SeriesResourceLinker.test.ts +699 -0
  47. package/Tests/Server/Utils/SeriesResourceLabels.test.ts +55 -0
  48. package/Tests/Server/Utils/Telemetry/InventoryEntityRegistry.test.ts +668 -0
  49. package/Tests/Types/API/URLMalformedTolerance.test.ts +301 -0
  50. package/Tests/Types/API/URLTelScheme.test.ts +261 -0
  51. package/Tests/Types/API/URLUnsupportedScheme.test.ts +148 -0
  52. package/Tests/Types/Billing/PayAsYouGoPricing.test.ts +64 -0
  53. package/Tests/Types/CustomField/CustomFieldTypeCorrespondence.test.ts +107 -0
  54. package/Tests/Types/Monitor/MonitorType.test.ts +62 -0
  55. package/Tests/Types/NetworkAutomation/RuleRunResult.test.ts +184 -0
  56. package/Tests/Types/Runbook/RunbookStepType.test.ts +124 -0
  57. package/Tests/Types/Workflow/BaseModelComponents.test.ts +17 -0
  58. package/Tests/UI/Components/Button.test.tsx +279 -0
  59. package/Tests/UI/Components/Charts/ChartXAxisDataKey.test.tsx +256 -0
  60. package/Tests/UI/Components/Charts/DataPointUtil.test.ts +323 -0
  61. package/Tests/UI/Components/DictionaryValuePlaceholderAndSuggestions.test.tsx +595 -0
  62. package/Tests/UI/Components/Icon.test.tsx +57 -0
  63. package/Tests/UI/Components/List.test.tsx +20 -3
  64. package/Tests/UI/Components/LogsSavedViewsDropdown.test.tsx +304 -0
  65. package/Tests/UI/Components/LogsViewerClearSavedView.test.tsx +179 -0
  66. package/Tests/UI/Components/ModelTable/CustomFieldColumns.test.tsx +349 -1
  67. package/Tests/UI/Components/Pagination.test.tsx +721 -146
  68. package/Tests/UI/Components/PaginationIntegration.test.tsx +386 -0
  69. package/Tests/UI/Components/PaginationUtil.test.ts +417 -0
  70. package/Tests/UI/Components/TelemetrySavedViewsDropdown.test.tsx +343 -0
  71. package/Tests/UI/Components/Workflow/ColumnEditor/ColumnControl.test.ts +289 -0
  72. package/Tests/UI/Components/Workflow/ColumnEditor/ColumnOperators.test.ts +271 -0
  73. package/Tests/UI/Components/Workflow/ColumnEditor/ColumnRow.test.ts +119 -0
  74. package/Tests/UI/Components/Workflow/ColumnEditor/ColumnRowSerialization.test.ts +968 -0
  75. package/Tests/UI/Components/Workflow/ModelColumnEditor.render.test.tsx +766 -0
  76. package/Tests/UI/Utils/RunNetworkRule.test.ts +320 -0
  77. package/Tests/Utils/APIRetryPolicy.test.ts +823 -0
  78. package/Tests/Utils/Monitor/NetworkDeviceRoleUtil.test.ts +502 -0
  79. package/Tests/Utils/Monitor/NetworkTopologyDeclaredHierarchy.test.ts +759 -0
  80. package/Tests/Utils/NetworkAutomation/RuleRunSummary.test.ts +286 -0
  81. package/Tests/Utils/Schema/BaseSchema.test.ts +651 -0
  82. package/Types/API/Protocol.ts +9 -0
  83. package/Types/API/URL.ts +286 -20
  84. package/Types/Billing/PayAsYouGoPricing.ts +47 -0
  85. package/Types/CustomField/CustomFieldType.ts +28 -0
  86. package/Types/Monitor/MonitorType.ts +11 -0
  87. package/Types/Monitor/SnmpMonitor/NetworkTopology.ts +13 -0
  88. package/Types/NetworkAutomation/RuleRunResult.ts +121 -0
  89. package/Types/Runbook/RunbookStepType.ts +23 -0
  90. package/UI/Components/AutocompleteTextInput/AutocompleteTextInput.tsx +7 -0
  91. package/UI/Components/Button/Button.tsx +14 -22
  92. package/UI/Components/Charts/Area/AreaChart.tsx +4 -2
  93. package/UI/Components/Charts/Bar/BarChart.tsx +4 -2
  94. package/UI/Components/Charts/ChartLibrary/Types/ChartDataPoint.ts +13 -0
  95. package/UI/Components/Charts/Line/LineChart.tsx +4 -2
  96. package/UI/Components/Charts/Types/XAxis/XAxis.ts +6 -0
  97. package/UI/Components/Charts/Utils/DataPoint.ts +15 -12
  98. package/UI/Components/Dictionary/Dictionary.tsx +4 -39
  99. package/UI/Components/Icon/Icon.tsx +1 -1
  100. package/UI/Components/LogsViewer/LogsViewer.tsx +5 -1
  101. package/UI/Components/LogsViewer/components/LogsFacetSidebar.tsx +8 -0
  102. package/UI/Components/LogsViewer/components/LogsPagination.tsx +29 -91
  103. package/UI/Components/LogsViewer/components/LogsViewerToolbar.tsx +2 -0
  104. package/UI/Components/LogsViewer/components/SavedViewsDropdown.tsx +66 -1
  105. package/UI/Components/ModelTable/CustomFieldColumns.tsx +55 -0
  106. package/UI/Components/Pagination/Pagination.tsx +373 -328
  107. package/UI/Components/Pagination/PaginationUtil.ts +263 -0
  108. package/UI/Components/Pagination/Screenshots/README.md +15 -0
  109. package/UI/Components/Pagination/Screenshots/pagination-before-after.png +0 -0
  110. package/UI/Components/Pagination/Screenshots/pagination-go-to-page-modal.png +0 -0
  111. package/UI/Components/Pagination/Screenshots/pagination-long-list.png +0 -0
  112. package/UI/Components/Pagination/Screenshots/pagination-mobile.png +0 -0
  113. package/UI/Components/Pagination/Screenshots/pagination-telemetry.png +0 -0
  114. package/UI/Components/TelemetryViewer/components/SavedViewsDropdown.tsx +66 -1
  115. package/UI/Components/TelemetryViewer/components/TelemetryPagination.tsx +38 -92
  116. package/UI/Components/TextArea/TextArea.tsx +3 -0
  117. package/UI/Components/Workflow/ArgumentsForm.tsx +18 -1
  118. package/UI/Components/Workflow/ColumnEditor/AddColumnDropdown.tsx +177 -0
  119. package/UI/Components/Workflow/ColumnEditor/ColumnConditionRow.tsx +243 -0
  120. package/UI/Components/Workflow/ColumnEditor/ColumnControl.ts +255 -0
  121. package/UI/Components/Workflow/ColumnEditor/ColumnFieldRow.tsx +178 -0
  122. package/UI/Components/Workflow/ColumnEditor/ColumnOperators.ts +206 -0
  123. package/UI/Components/Workflow/ColumnEditor/ColumnRow.ts +157 -0
  124. package/UI/Components/Workflow/ColumnEditor/ColumnRowSerialization.ts +517 -0
  125. package/UI/Components/Workflow/ColumnEditor/ColumnValueInput.tsx +482 -0
  126. package/UI/Components/Workflow/ColumnEditor/ModelQueryBuilder.tsx +131 -0
  127. package/UI/Components/Workflow/ColumnEditor/ModelRecordForm.tsx +163 -0
  128. package/UI/Components/Workflow/ModelColumnEditor.tsx +284 -100
  129. package/UI/Utils/NetworkAutomation/RunNetworkRule.ts +122 -0
  130. package/Utils/API.ts +243 -36
  131. package/Utils/Monitor/NetworkDeviceRoleUtil.ts +45 -0
  132. package/Utils/Monitor/NetworkTopologyUtil.ts +42 -2
  133. package/Utils/NetworkAutomation/RuleRunSummary.ts +147 -0
  134. package/build/dist/Models/DatabaseModels/NetworkDevice.js +45 -0
  135. package/build/dist/Models/DatabaseModels/NetworkDevice.js.map +1 -1
  136. package/build/dist/Models/DatabaseModels/NetworkDeviceLink.js +115 -0
  137. package/build/dist/Models/DatabaseModels/NetworkDeviceLink.js.map +1 -1
  138. package/build/dist/Models/DatabaseModels/RunnerJob.js +17 -2
  139. package/build/dist/Models/DatabaseModels/RunnerJob.js.map +1 -1
  140. package/build/dist/Server/API/LlmProviderAPI.js +9 -1
  141. package/build/dist/Server/API/LlmProviderAPI.js.map +1 -1
  142. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787400000000-AddDeviceRoleAndDeclaredLinkParent.js +33 -0
  143. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1787400000000-AddDeviceRoleAndDeclaredLinkParent.js.map +1 -0
  144. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +2 -0
  145. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  146. package/build/dist/Server/Services/NetworkDeviceLabelRuleEngineService.js +202 -0
  147. package/build/dist/Server/Services/NetworkDeviceLabelRuleEngineService.js.map +1 -1
  148. package/build/dist/Server/Services/NetworkDeviceLinkService.js +253 -1
  149. package/build/dist/Server/Services/NetworkDeviceLinkService.js.map +1 -1
  150. package/build/dist/Server/Services/NetworkDeviceService.js +223 -12
  151. package/build/dist/Server/Services/NetworkDeviceService.js.map +1 -1
  152. package/build/dist/Server/Services/RunnerJobService.js +20 -2
  153. package/build/dist/Server/Services/RunnerJobService.js.map +1 -1
  154. package/build/dist/Server/Types/Billing/MeteredPlan/AllMeteredPlans.js +12 -5
  155. package/build/dist/Server/Types/Billing/MeteredPlan/AllMeteredPlans.js.map +1 -1
  156. package/build/dist/Server/Types/Database/JSONColumnQuery.js +40 -4
  157. package/build/dist/Server/Types/Database/JSONColumnQuery.js.map +1 -1
  158. package/build/dist/Server/Utils/LLM/LLMService.js +78 -22
  159. package/build/dist/Server/Utils/LLM/LLMService.js.map +1 -1
  160. package/build/dist/Server/Utils/Monitor/MonitorAlert.js +22 -98
  161. package/build/dist/Server/Utils/Monitor/MonitorAlert.js.map +1 -1
  162. package/build/dist/Server/Utils/Monitor/MonitorIncident.js +7 -254
  163. package/build/dist/Server/Utils/Monitor/MonitorIncident.js.map +1 -1
  164. package/build/dist/Server/Utils/Monitor/MonitorMaintenanceSuppression.js +14 -2
  165. package/build/dist/Server/Utils/Monitor/MonitorMaintenanceSuppression.js.map +1 -1
  166. package/build/dist/Server/Utils/Monitor/SeriesResourceLabels.js +27 -0
  167. package/build/dist/Server/Utils/Monitor/SeriesResourceLabels.js.map +1 -1
  168. package/build/dist/Server/Utils/Monitor/SeriesResourceLinker.js +285 -0
  169. package/build/dist/Server/Utils/Monitor/SeriesResourceLinker.js.map +1 -0
  170. package/build/dist/Server/Utils/SSRFProtection.js +5 -4
  171. package/build/dist/Server/Utils/SSRFProtection.js.map +1 -1
  172. package/build/dist/Server/Utils/Telemetry/InventoryEntityRegistry.js +128 -35
  173. package/build/dist/Server/Utils/Telemetry/InventoryEntityRegistry.js.map +1 -1
  174. package/build/dist/Types/API/Protocol.js +9 -0
  175. package/build/dist/Types/API/Protocol.js.map +1 -1
  176. package/build/dist/Types/API/URL.js +241 -18
  177. package/build/dist/Types/API/URL.js.map +1 -1
  178. package/build/dist/Types/Billing/PayAsYouGoPricing.js +41 -0
  179. package/build/dist/Types/Billing/PayAsYouGoPricing.js.map +1 -0
  180. package/build/dist/Types/CustomField/CustomFieldType.js +26 -0
  181. package/build/dist/Types/CustomField/CustomFieldType.js.map +1 -1
  182. package/build/dist/Types/Monitor/MonitorType.js +10 -0
  183. package/build/dist/Types/Monitor/MonitorType.js.map +1 -1
  184. package/build/dist/Types/NetworkAutomation/RuleRunResult.js +39 -0
  185. package/build/dist/Types/NetworkAutomation/RuleRunResult.js.map +1 -0
  186. package/build/dist/Types/Runbook/RunbookStepType.js +21 -0
  187. package/build/dist/Types/Runbook/RunbookStepType.js.map +1 -1
  188. package/build/dist/UI/Components/AutocompleteTextInput/AutocompleteTextInput.js +1 -1
  189. package/build/dist/UI/Components/AutocompleteTextInput/AutocompleteTextInput.js.map +1 -1
  190. package/build/dist/UI/Components/Button/Button.js +10 -16
  191. package/build/dist/UI/Components/Button/Button.js.map +1 -1
  192. package/build/dist/UI/Components/Charts/Area/AreaChart.js +2 -1
  193. package/build/dist/UI/Components/Charts/Area/AreaChart.js.map +1 -1
  194. package/build/dist/UI/Components/Charts/Bar/BarChart.js +2 -1
  195. package/build/dist/UI/Components/Charts/Bar/BarChart.js.map +1 -1
  196. package/build/dist/UI/Components/Charts/ChartLibrary/Types/ChartDataPoint.js +12 -0
  197. package/build/dist/UI/Components/Charts/ChartLibrary/Types/ChartDataPoint.js.map +1 -1
  198. package/build/dist/UI/Components/Charts/Line/LineChart.js +2 -1
  199. package/build/dist/UI/Components/Charts/Line/LineChart.js.map +1 -1
  200. package/build/dist/UI/Components/Charts/Utils/DataPoint.js +17 -10
  201. package/build/dist/UI/Components/Charts/Utils/DataPoint.js.map +1 -1
  202. package/build/dist/UI/Components/Dictionary/Dictionary.js +4 -18
  203. package/build/dist/UI/Components/Dictionary/Dictionary.js.map +1 -1
  204. package/build/dist/UI/Components/Icon/Icon.js +1 -1
  205. package/build/dist/UI/Components/Icon/Icon.js.map +1 -1
  206. package/build/dist/UI/Components/LogsViewer/LogsViewer.js +3 -3
  207. package/build/dist/UI/Components/LogsViewer/LogsViewer.js.map +1 -1
  208. package/build/dist/UI/Components/LogsViewer/components/LogsFacetSidebar.js +5 -1
  209. package/build/dist/UI/Components/LogsViewer/components/LogsFacetSidebar.js.map +1 -1
  210. package/build/dist/UI/Components/LogsViewer/components/LogsPagination.js +14 -44
  211. package/build/dist/UI/Components/LogsViewer/components/LogsPagination.js.map +1 -1
  212. package/build/dist/UI/Components/LogsViewer/components/LogsViewerToolbar.js +1 -1
  213. package/build/dist/UI/Components/LogsViewer/components/LogsViewerToolbar.js.map +1 -1
  214. package/build/dist/UI/Components/LogsViewer/components/SavedViewsDropdown.js +20 -2
  215. package/build/dist/UI/Components/LogsViewer/components/SavedViewsDropdown.js.map +1 -1
  216. package/build/dist/UI/Components/ModelTable/CustomFieldColumns.js +42 -0
  217. package/build/dist/UI/Components/ModelTable/CustomFieldColumns.js.map +1 -1
  218. package/build/dist/UI/Components/Pagination/Pagination.js +174 -199
  219. package/build/dist/UI/Components/Pagination/Pagination.js.map +1 -1
  220. package/build/dist/UI/Components/Pagination/PaginationUtil.js +160 -0
  221. package/build/dist/UI/Components/Pagination/PaginationUtil.js.map +1 -0
  222. package/build/dist/UI/Components/TelemetryViewer/components/SavedViewsDropdown.js +20 -2
  223. package/build/dist/UI/Components/TelemetryViewer/components/SavedViewsDropdown.js.map +1 -1
  224. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryPagination.js +23 -47
  225. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryPagination.js.map +1 -1
  226. package/build/dist/UI/Components/TextArea/TextArea.js +1 -1
  227. package/build/dist/UI/Components/TextArea/TextArea.js.map +1 -1
  228. package/build/dist/UI/Components/Workflow/ArgumentsForm.js +14 -2
  229. package/build/dist/UI/Components/Workflow/ArgumentsForm.js.map +1 -1
  230. package/build/dist/UI/Components/Workflow/ColumnEditor/AddColumnDropdown.js +86 -0
  231. package/build/dist/UI/Components/Workflow/ColumnEditor/AddColumnDropdown.js.map +1 -0
  232. package/build/dist/UI/Components/Workflow/ColumnEditor/ColumnConditionRow.js +119 -0
  233. package/build/dist/UI/Components/Workflow/ColumnEditor/ColumnConditionRow.js.map +1 -0
  234. package/build/dist/UI/Components/Workflow/ColumnEditor/ColumnControl.js +206 -0
  235. package/build/dist/UI/Components/Workflow/ColumnEditor/ColumnControl.js.map +1 -0
  236. package/build/dist/UI/Components/Workflow/ColumnEditor/ColumnFieldRow.js +57 -0
  237. package/build/dist/UI/Components/Workflow/ColumnEditor/ColumnFieldRow.js.map +1 -0
  238. package/build/dist/UI/Components/Workflow/ColumnEditor/ColumnOperators.js +150 -0
  239. package/build/dist/UI/Components/Workflow/ColumnEditor/ColumnOperators.js.map +1 -0
  240. package/build/dist/UI/Components/Workflow/ColumnEditor/ColumnRow.js +67 -0
  241. package/build/dist/UI/Components/Workflow/ColumnEditor/ColumnRow.js.map +1 -0
  242. package/build/dist/UI/Components/Workflow/ColumnEditor/ColumnRowSerialization.js +309 -0
  243. package/build/dist/UI/Components/Workflow/ColumnEditor/ColumnRowSerialization.js.map +1 -0
  244. package/build/dist/UI/Components/Workflow/ColumnEditor/ColumnValueInput.js +204 -0
  245. package/build/dist/UI/Components/Workflow/ColumnEditor/ColumnValueInput.js.map +1 -0
  246. package/build/dist/UI/Components/Workflow/ColumnEditor/ModelQueryBuilder.js +66 -0
  247. package/build/dist/UI/Components/Workflow/ColumnEditor/ModelQueryBuilder.js.map +1 -0
  248. package/build/dist/UI/Components/Workflow/ColumnEditor/ModelRecordForm.js +83 -0
  249. package/build/dist/UI/Components/Workflow/ColumnEditor/ModelRecordForm.js.map +1 -0
  250. package/build/dist/UI/Components/Workflow/ModelColumnEditor.js +187 -68
  251. package/build/dist/UI/Components/Workflow/ModelColumnEditor.js.map +1 -1
  252. package/build/dist/UI/Utils/NetworkAutomation/RunNetworkRule.js +75 -0
  253. package/build/dist/UI/Utils/NetworkAutomation/RunNetworkRule.js.map +1 -0
  254. package/build/dist/Utils/API.js +175 -34
  255. package/build/dist/Utils/API.js.map +1 -1
  256. package/build/dist/Utils/Monitor/NetworkDeviceRoleUtil.js +37 -0
  257. package/build/dist/Utils/Monitor/NetworkDeviceRoleUtil.js.map +1 -1
  258. package/build/dist/Utils/Monitor/NetworkTopologyUtil.js +25 -3
  259. package/build/dist/Utils/Monitor/NetworkTopologyUtil.js.map +1 -1
  260. package/build/dist/Utils/NetworkAutomation/RuleRunSummary.js +78 -0
  261. package/build/dist/Utils/NetworkAutomation/RuleRunSummary.js.map +1 -0
  262. package/package.json +1 -1
@@ -0,0 +1,469 @@
1
+ import CephCluster from "../../../Models/DatabaseModels/CephCluster";
2
+ import DockerHost from "../../../Models/DatabaseModels/DockerHost";
3
+ import DockerSwarmCluster from "../../../Models/DatabaseModels/DockerSwarmCluster";
4
+ import Host from "../../../Models/DatabaseModels/Host";
5
+ import IoTFleet from "../../../Models/DatabaseModels/IoTFleet";
6
+ import KubernetesCluster from "../../../Models/DatabaseModels/KubernetesCluster";
7
+ import PodmanHost from "../../../Models/DatabaseModels/PodmanHost";
8
+ import ProxmoxCluster from "../../../Models/DatabaseModels/ProxmoxCluster";
9
+ import Service from "../../../Models/DatabaseModels/Service";
10
+ import Includes from "../../../Types/BaseDatabase/Includes";
11
+ import { LIMIT_PER_PROJECT } from "../../../Types/Database/LimitMax";
12
+ import { JSONObject } from "../../../Types/JSON";
13
+ import ObjectID from "../../../Types/ObjectID";
14
+ import CephClusterService from "../../Services/CephClusterService";
15
+ import DockerHostService from "../../Services/DockerHostService";
16
+ import DockerSwarmClusterService from "../../Services/DockerSwarmClusterService";
17
+ import HostService from "../../Services/HostService";
18
+ import IoTFleetService from "../../Services/IoTFleetService";
19
+ import KubernetesClusterService from "../../Services/KubernetesClusterService";
20
+ import PodmanHostService from "../../Services/PodmanHostService";
21
+ import ProxmoxClusterService from "../../Services/ProxmoxClusterService";
22
+ import ServiceService from "../../Services/ServiceService";
23
+ import { MonitorClusterContext } from "./MonitorClusterContext";
24
+ import SeriesResourceLabels, {
25
+ SeriesResourceRefs,
26
+ } from "./SeriesResourceLabels";
27
+
28
+ /*
29
+ * A grouped monitor opens one alert/incident per breaching series, and
30
+ * each series carries the identity of the resource it came from in its
31
+ * labels. This module turns those labels into real, project-scoped
32
+ * resource rows and attaches them to the alert/incident, so "Affected
33
+ * Resources", the per-resource Activity tabs, the sidebar badge counts
34
+ * and the resource-owner/label inheritance rules all see the host (or
35
+ * cluster, or service) the event is actually about.
36
+ *
37
+ * Alerts and incidents MUST agree here. They used to disagree: the
38
+ * incident path resolved every resource type through the shared
39
+ * SeriesResourceLabels key map while the alert path read two hard-coded
40
+ * label spellings (`resource.host.name` / `host.name`) inline, so an
41
+ * alert grouped by the far more common `oneuptime.host.name` stamp
42
+ * linked nothing at all. Both paths now call this one module.
43
+ */
44
+
45
+ /*
46
+ * Structurally satisfied by both Alert and Incident — every relation
47
+ * below is declared identically on the two models. Typed with
48
+ * `| undefined` so the models' `public hosts?: Array<Host> = undefined;`
49
+ * shape stays assignable under exactOptionalPropertyTypes.
50
+ */
51
+ export interface SeriesLinkableModel {
52
+ hosts?: Array<Host> | undefined;
53
+ dockerHosts?: Array<DockerHost> | undefined;
54
+ podmanHosts?: Array<PodmanHost> | undefined;
55
+ kubernetesClusters?: Array<KubernetesCluster> | undefined;
56
+ services?: Array<Service> | undefined;
57
+ proxmoxClusters?: Array<ProxmoxCluster> | undefined;
58
+ cephClusters?: Array<CephCluster> | undefined;
59
+ dockerSwarmClusters?: Array<DockerSwarmCluster> | undefined;
60
+ iotFleets?: Array<IoTFleet> | undefined;
61
+ }
62
+
63
+ /*
64
+ * Database ids of the resources one series points at, by type. Empty
65
+ * arrays for every type the series says nothing about.
66
+ */
67
+ export interface SeriesResolvedResourceIds {
68
+ hostIds: Array<string>;
69
+ dockerHostIds: Array<string>;
70
+ podmanHostIds: Array<string>;
71
+ kubernetesClusterIds: Array<string>;
72
+ serviceIds: Array<string>;
73
+ proxmoxClusterIds: Array<string>;
74
+ cephClusterIds: Array<string>;
75
+ dockerSwarmClusterIds: Array<string>;
76
+ iotFleetIds: Array<string>;
77
+ }
78
+
79
+ /*
80
+ * One resource type's lookup recipe: where its ids and names come from
81
+ * in the extracted refs, which column its name maps to, and which
82
+ * service reads the table.
83
+ */
84
+ interface ResourceResolutionSpec {
85
+ ids: Array<string>;
86
+ names: Array<string>;
87
+ nameColumn: string;
88
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
89
+ findBy: (args: any) => Promise<Array<{ _id?: string | undefined }>>;
90
+ }
91
+
92
+ export default class SeriesResourceLinker {
93
+ /*
94
+ * Resolve a series' labels to project-scoped database ids, without
95
+ * touching any model. Lookups are ALWAYS project-scoped: `isRoot`
96
+ * bypasses row-level access control, and a stale or hostile
97
+ * `oneuptime.*.id` stamp must never be able to pull a row in from
98
+ * another tenant.
99
+ */
100
+ public static async resolveResourcesFromSeriesLabels(input: {
101
+ seriesLabels: JSONObject;
102
+ projectId: ObjectID;
103
+ }): Promise<SeriesResolvedResourceIds> {
104
+ const refs: SeriesResourceRefs = SeriesResourceLabels.extractResourceRefs(
105
+ input.seriesLabels,
106
+ );
107
+
108
+ /*
109
+ * Proxmox / Ceph / Docker Swarm / IoT carry no `oneuptime.*.id`
110
+ * stamp at ingest — they are addressable by name only — so their
111
+ * `ids` lists are empty by construction, not by omission.
112
+ */
113
+ const specs: Array<ResourceResolutionSpec> = [
114
+ {
115
+ ids: refs.hostIds,
116
+ names: refs.hostNames,
117
+ nameColumn: "hostIdentifier",
118
+ findBy: HostService.findBy.bind(HostService),
119
+ },
120
+ {
121
+ ids: refs.dockerHostIds,
122
+ names: refs.dockerHostNames,
123
+ nameColumn: "hostIdentifier",
124
+ findBy: DockerHostService.findBy.bind(DockerHostService),
125
+ },
126
+ {
127
+ ids: refs.podmanHostIds,
128
+ names: refs.podmanHostNames,
129
+ nameColumn: "hostIdentifier",
130
+ findBy: PodmanHostService.findBy.bind(PodmanHostService),
131
+ },
132
+ {
133
+ ids: refs.kubernetesClusterIds,
134
+ names: refs.kubernetesClusterNames,
135
+ nameColumn: "clusterIdentifier",
136
+ findBy: KubernetesClusterService.findBy.bind(KubernetesClusterService),
137
+ },
138
+ {
139
+ ids: refs.serviceIds,
140
+ names: refs.serviceNames,
141
+ nameColumn: "name",
142
+ findBy: ServiceService.findBy.bind(ServiceService),
143
+ },
144
+ {
145
+ ids: [],
146
+ names: refs.proxmoxClusterNames,
147
+ nameColumn: "name",
148
+ findBy: ProxmoxClusterService.findBy.bind(ProxmoxClusterService),
149
+ },
150
+ {
151
+ ids: [],
152
+ names: refs.cephClusterNames,
153
+ nameColumn: "name",
154
+ findBy: CephClusterService.findBy.bind(CephClusterService),
155
+ },
156
+ {
157
+ ids: [],
158
+ names: refs.dockerSwarmClusterNames,
159
+ nameColumn: "name",
160
+ findBy: DockerSwarmClusterService.findBy.bind(
161
+ DockerSwarmClusterService,
162
+ ),
163
+ },
164
+ {
165
+ ids: [],
166
+ names: refs.iotFleetNames,
167
+ nameColumn: "name",
168
+ findBy: IoTFleetService.findBy.bind(IoTFleetService),
169
+ },
170
+ ];
171
+
172
+ const [
173
+ hostIds,
174
+ dockerHostIds,
175
+ podmanHostIds,
176
+ kubernetesClusterIds,
177
+ serviceIds,
178
+ proxmoxClusterIds,
179
+ cephClusterIds,
180
+ dockerSwarmClusterIds,
181
+ iotFleetIds,
182
+ ] = await Promise.all(
183
+ specs.map((spec: ResourceResolutionSpec): Promise<Array<string>> => {
184
+ return this.resolveResourceIds({
185
+ ids: spec.ids,
186
+ names: spec.names,
187
+ nameColumn: spec.nameColumn,
188
+ projectId: input.projectId,
189
+ findBy: spec.findBy,
190
+ });
191
+ }),
192
+ );
193
+
194
+ return {
195
+ hostIds: hostIds || [],
196
+ dockerHostIds: dockerHostIds || [],
197
+ podmanHostIds: podmanHostIds || [],
198
+ kubernetesClusterIds: kubernetesClusterIds || [],
199
+ serviceIds: serviceIds || [],
200
+ proxmoxClusterIds: proxmoxClusterIds || [],
201
+ cephClusterIds: cephClusterIds || [],
202
+ dockerSwarmClusterIds: dockerSwarmClusterIds || [],
203
+ iotFleetIds: iotFleetIds || [],
204
+ };
205
+ }
206
+
207
+ /*
208
+ * Resolve the series' resources and MERGE them onto the alert/incident.
209
+ * Merging (rather than assigning) matters because attachClusterContext
210
+ * writes the same four cluster relations from the monitor's step
211
+ * config; whichever runs second must not erase the other's work.
212
+ *
213
+ * Relations the series says nothing about are left untouched —
214
+ * `undefined`, not `[]` — so an ungrouped event and an event whose
215
+ * resource has been deleted both stay clean rather than persisting an
216
+ * empty join set.
217
+ *
218
+ * The attached rows are id-only stubs. Every in-memory consumer of a
219
+ * freshly created alert/incident reads ids (the owner-inheritance rule
220
+ * engine); anything that needs a name re-reads the persisted relation.
221
+ */
222
+ public static async linkSeriesResourcesToModel(input: {
223
+ model: SeriesLinkableModel;
224
+ seriesLabels: JSONObject;
225
+ projectId: ObjectID;
226
+ }): Promise<void> {
227
+ const resolved: SeriesResolvedResourceIds =
228
+ await this.resolveResourcesFromSeriesLabels({
229
+ seriesLabels: input.seriesLabels,
230
+ projectId: input.projectId,
231
+ });
232
+
233
+ this.mergeResolvedIdsIntoModel({
234
+ model: input.model,
235
+ resolved: resolved,
236
+ });
237
+ }
238
+
239
+ /*
240
+ * Attach the cluster ids resolved from the monitor's step config
241
+ * (Proxmox / Ceph / Docker Swarm / IoT), merging with — never
242
+ * overwriting — anything the series-label path already linked. Both
243
+ * paths can resolve the same cluster, so this dedupes by id. Unlike
244
+ * the label path this runs for ungrouped events too: those monitor
245
+ * types get their cluster identity from the step config alone.
246
+ */
247
+ public static attachClusterContext(input: {
248
+ model: SeriesLinkableModel;
249
+ clusterContext: MonitorClusterContext;
250
+ }): void {
251
+ this.mergeResolvedIdsIntoModel({
252
+ model: input.model,
253
+ resolved: {
254
+ hostIds: [],
255
+ dockerHostIds: [],
256
+ podmanHostIds: [],
257
+ kubernetesClusterIds: [],
258
+ serviceIds: [],
259
+ proxmoxClusterIds: input.clusterContext.proxmoxClusterIds,
260
+ cephClusterIds: input.clusterContext.cephClusterIds,
261
+ dockerSwarmClusterIds: input.clusterContext.dockerSwarmClusterIds,
262
+ iotFleetIds: input.clusterContext.iotFleetIds,
263
+ },
264
+ });
265
+ }
266
+
267
+ private static mergeResolvedIdsIntoModel(input: {
268
+ model: SeriesLinkableModel;
269
+ resolved: SeriesResolvedResourceIds;
270
+ }): void {
271
+ const model: SeriesLinkableModel = input.model;
272
+ const resolved: SeriesResolvedResourceIds = input.resolved;
273
+
274
+ if (resolved.hostIds.length > 0) {
275
+ model.hosts = this.mergeById(model.hosts, resolved.hostIds, (): Host => {
276
+ return new Host();
277
+ });
278
+ }
279
+
280
+ if (resolved.dockerHostIds.length > 0) {
281
+ model.dockerHosts = this.mergeById(
282
+ model.dockerHosts,
283
+ resolved.dockerHostIds,
284
+ (): DockerHost => {
285
+ return new DockerHost();
286
+ },
287
+ );
288
+ }
289
+
290
+ if (resolved.podmanHostIds.length > 0) {
291
+ model.podmanHosts = this.mergeById(
292
+ model.podmanHosts,
293
+ resolved.podmanHostIds,
294
+ (): PodmanHost => {
295
+ return new PodmanHost();
296
+ },
297
+ );
298
+ }
299
+
300
+ if (resolved.kubernetesClusterIds.length > 0) {
301
+ model.kubernetesClusters = this.mergeById(
302
+ model.kubernetesClusters,
303
+ resolved.kubernetesClusterIds,
304
+ (): KubernetesCluster => {
305
+ return new KubernetesCluster();
306
+ },
307
+ );
308
+ }
309
+
310
+ if (resolved.serviceIds.length > 0) {
311
+ model.services = this.mergeById(
312
+ model.services,
313
+ resolved.serviceIds,
314
+ (): Service => {
315
+ return new Service();
316
+ },
317
+ );
318
+ }
319
+
320
+ if (resolved.proxmoxClusterIds.length > 0) {
321
+ model.proxmoxClusters = this.mergeById(
322
+ model.proxmoxClusters,
323
+ resolved.proxmoxClusterIds,
324
+ (): ProxmoxCluster => {
325
+ return new ProxmoxCluster();
326
+ },
327
+ );
328
+ }
329
+
330
+ if (resolved.cephClusterIds.length > 0) {
331
+ model.cephClusters = this.mergeById(
332
+ model.cephClusters,
333
+ resolved.cephClusterIds,
334
+ (): CephCluster => {
335
+ return new CephCluster();
336
+ },
337
+ );
338
+ }
339
+
340
+ if (resolved.dockerSwarmClusterIds.length > 0) {
341
+ model.dockerSwarmClusters = this.mergeById(
342
+ model.dockerSwarmClusters,
343
+ resolved.dockerSwarmClusterIds,
344
+ (): DockerSwarmCluster => {
345
+ return new DockerSwarmCluster();
346
+ },
347
+ );
348
+ }
349
+
350
+ if (resolved.iotFleetIds.length > 0) {
351
+ model.iotFleets = this.mergeById(
352
+ model.iotFleets,
353
+ resolved.iotFleetIds,
354
+ (): IoTFleet => {
355
+ return new IoTFleet();
356
+ },
357
+ );
358
+ }
359
+ }
360
+
361
+ /*
362
+ * Append the ids that aren't attached yet, preserving whatever is
363
+ * already on the relation. A duplicate id in the array would violate
364
+ * the join table's composite primary key on save, so dedupe by the
365
+ * stringified `_id`.
366
+ */
367
+ private static mergeById<T extends { _id?: string | undefined }>(
368
+ existing: Array<T> | undefined,
369
+ incomingIds: Array<string>,
370
+ create: () => T,
371
+ ): Array<T> {
372
+ const merged: Array<T> = [...(existing || [])];
373
+ const seenIds: Set<string> = new Set<string>(
374
+ merged.map((item: T): string => {
375
+ return String(item._id);
376
+ }),
377
+ );
378
+
379
+ for (const id of incomingIds) {
380
+ if (seenIds.has(id)) {
381
+ continue;
382
+ }
383
+
384
+ seenIds.add(id);
385
+
386
+ const item: T = create();
387
+ item._id = id;
388
+ merged.push(item);
389
+ }
390
+
391
+ return merged;
392
+ }
393
+
394
+ /*
395
+ * Turn one resource type's ids and names into deduped database ids.
396
+ * Costs zero round-trips when the series carries neither, which is the
397
+ * common case for most of the nine types on any given series.
398
+ *
399
+ * Name matching is exact. Every identifier column read here is written
400
+ * by ingest from the same attribute the series label carries — host
401
+ * identifiers are canonicalized on both sides — so exact matching is
402
+ * what keeps a lookup from straying onto a neighbouring row.
403
+ */
404
+ private static async resolveResourceIds(input: {
405
+ ids: Array<string>;
406
+ names: Array<string>;
407
+ nameColumn: string;
408
+ projectId: ObjectID;
409
+ /*
410
+ * Loosely typed because each resource service has its own
411
+ * `Query<TBaseModel>` shape and we deliberately abstract over
412
+ * them. We only need the row's `_id` back, which every model
413
+ * exposes via `DatabaseBaseModel`.
414
+ */
415
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
416
+ findBy: (args: any) => Promise<Array<{ _id?: string | undefined }>>;
417
+ }): Promise<Array<string>> {
418
+ if (input.ids.length === 0 && input.names.length === 0) {
419
+ return [];
420
+ }
421
+
422
+ const resolved: Set<string> = new Set<string>();
423
+
424
+ const lookups: Array<Promise<Array<{ _id?: string | undefined }>>> = [];
425
+
426
+ if (input.ids.length > 0) {
427
+ lookups.push(
428
+ input.findBy({
429
+ query: {
430
+ projectId: input.projectId,
431
+ _id: new Includes(input.ids),
432
+ },
433
+ select: { _id: true },
434
+ skip: 0,
435
+ limit: LIMIT_PER_PROJECT,
436
+ props: { isRoot: true },
437
+ }),
438
+ );
439
+ }
440
+
441
+ if (input.names.length > 0) {
442
+ lookups.push(
443
+ input.findBy({
444
+ query: {
445
+ projectId: input.projectId,
446
+ [input.nameColumn]: new Includes(input.names),
447
+ },
448
+ select: { _id: true },
449
+ skip: 0,
450
+ limit: LIMIT_PER_PROJECT,
451
+ props: { isRoot: true },
452
+ }),
453
+ );
454
+ }
455
+
456
+ const buckets: Array<Array<{ _id?: string | undefined }>> =
457
+ await Promise.all(lookups);
458
+
459
+ for (const bucket of buckets) {
460
+ for (const row of bucket) {
461
+ if (row._id) {
462
+ resolved.add(String(row._id));
463
+ }
464
+ }
465
+ }
466
+
467
+ return Array.from(resolved);
468
+ }
469
+ }
@@ -82,10 +82,11 @@ export default class SSRFProtection {
82
82
  rawUrl: string | URL,
83
83
  ): Promise<void> {
84
84
  /*
85
- * URL.fromString only knows http/https/ws/wss/mongodb/mailto and silently
86
- * DEFAULTS anything else to https - "file:///etc/passwd" comes back as
87
- * host "file", not as a file: URL - so the protocol check below never sees
88
- * the scheme the caller actually wrote. Read it off the raw string first.
85
+ * URL.fromString only knows http/https/ws/wss/mongodb/mailto/tel/sms and
86
+ * silently DEFAULTS anything else to https - "file:///etc/passwd" comes
87
+ * back as host "file", not as a file: URL - so the protocol check below
88
+ * never sees the scheme the caller actually wrote. Read it off the raw
89
+ * string first.
89
90
  *
90
91
  * The ":" must be followed by "/" or this would treat the host in a
91
92
  * scheme-less "example.com:8080/hook" as a scheme and reject it.