@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
@@ -298,7 +298,11 @@ export default class WorkflowVariable extends BaseModel {
298
298
  Permission.CreateWorkflowVariable,
299
299
  ],
300
300
  read: [],
301
- update: [Permission.ProjectOwner, Permission.ProjectAdmin],
301
+ update: [
302
+ Permission.ProjectOwner,
303
+ Permission.ProjectAdmin,
304
+ Permission.EditWorkflowVariable,
305
+ ],
302
306
  })
303
307
  @TableColumn({
304
308
  required: true,
@@ -1,6 +1,9 @@
1
1
  import Alert from "../../Models/DatabaseModels/Alert";
2
2
  import NotFoundException from "../../Types/Exception/NotFoundException";
3
3
  import BadDataException from "../../Types/Exception/BadDataException";
4
+ import DatabaseCommonInteractionPropsUtil, {
5
+ PermissionType,
6
+ } from "../../Types/BaseDatabase/DatabaseCommonInteractionPropsUtil";
4
7
  import ObjectID from "../../Types/ObjectID";
5
8
  import AlertService, {
6
9
  Service as AlertServiceType,
@@ -21,7 +24,7 @@ import AlertAIContextBuilder, {
21
24
  AlertContextData,
22
25
  } from "../Utils/AI/AlertAIContextBuilder";
23
26
  import JSONFunctions from "../../Types/JSONFunctions";
24
- import Permission from "../../Types/Permission";
27
+ import Permission, { UserPermission } from "../../Types/Permission";
25
28
 
26
29
  export default class AlertAPI extends BaseAPI<Alert, AlertServiceType> {
27
30
  public constructor() {
@@ -62,22 +65,34 @@ export default class AlertAPI extends BaseAPI<Alert, AlertServiceType> {
62
65
  const props: DatabaseCommonInteractionProps =
63
66
  await CommonAPI.getDatabaseCommonInteractionProps(req);
64
67
 
65
- // Verify user has permission
66
- const permissions: Array<Permission> | undefined = props
67
- .userTenantAccessPermission?.["permissions"] as
68
- | Array<Permission>
69
- | undefined;
70
-
71
- const hasPermission: boolean = permissions
72
- ? permissions.some((p: Permission) => {
73
- return (
74
- p === Permission.ProjectOwner ||
75
- p === Permission.ProjectAdmin ||
76
- p === Permission.EditAlert ||
77
- p === Permission.CreateAlertInternalNote
78
- );
79
- })
80
- : false;
68
+ CommonAPI.assertTenantScoped(props);
69
+
70
+ /*
71
+ * Read through getUserPermissions(Allow) rather than off
72
+ * userTenantAccessPermission directly. That dictionary is keyed by project
73
+ * id and its entries hold GRANTS AND DENIALS together, discriminated only
74
+ * by isBlockPermission, so the previous
75
+ * `userTenantAccessPermission["permissions"]` read was always undefined
76
+ * and denied every caller who was not a master admin. Mapping the array
77
+ * raw would swing the other way and count a team's explicit block
78
+ * entry for one of these permissions as a grant of it.
79
+ */
80
+ const permissions: Array<Permission> =
81
+ DatabaseCommonInteractionPropsUtil.getUserPermissions(
82
+ props,
83
+ PermissionType.Allow,
84
+ ).map((userPermission: UserPermission) => {
85
+ return userPermission.permission;
86
+ });
87
+
88
+ const hasPermission: boolean = permissions.some((p: Permission) => {
89
+ return (
90
+ p === Permission.ProjectOwner ||
91
+ p === Permission.ProjectAdmin ||
92
+ p === Permission.EditAlert ||
93
+ p === Permission.CreateAlertInternalNote
94
+ );
95
+ });
81
96
 
82
97
  if (!hasPermission && !props.isMasterAdmin) {
83
98
  throw new BadDataException(
@@ -22,9 +22,10 @@ import {
22
22
  LIMIT_PER_PROJECT,
23
23
  } from "../../Types/Database/LimitMax";
24
24
  import PartialEntity from "../../Types/Database/PartialEntity";
25
+ import BadDataException from "../../Types/Exception/BadDataException";
25
26
  import BadRequestException from "../../Types/Exception/BadRequestException";
26
27
  import NotAuthorizedException from "../../Types/Exception/NotAuthorizedException";
27
- import { JSONObject } from "../../Types/JSON";
28
+ import { JSONObject, JSONValue } from "../../Types/JSON";
28
29
  import JSONFunctions from "../../Types/JSONFunctions";
29
30
  import ObjectID from "../../Types/ObjectID";
30
31
  import { UserPermission } from "../../Types/Permission";
@@ -398,15 +399,43 @@ export default class BaseAPI<
398
399
  const objectId: ObjectID = new ObjectID(idParam);
399
400
  const objectIdString: string = objectId.toString();
400
401
  const body: JSONObject = req.body;
402
+ const dataInBody: JSONValue | undefined = body["data"];
403
+
404
+ /*
405
+ * The update payload has to be wrapped as { "data": { ...columns... } }.
406
+ * A flat body has no "data" key, and deserializing that undefined handed
407
+ * back an empty object: the update then matched the row, wrote no columns
408
+ * at all, and still answered 200. Callers were told the write succeeded
409
+ * while their fields were dropped on the floor.
410
+ */
411
+ if (
412
+ !dataInBody ||
413
+ typeof dataInBody !== "object" ||
414
+ Array.isArray(dataInBody)
415
+ ) {
416
+ throw new BadDataException(
417
+ 'Invalid request body. The update payload should be an object of the form { "data": { ...fields to update... } }.',
418
+ );
419
+ }
401
420
 
402
421
  const item: PartialEntity<TBaseModel> = JSONFunctions.deserialize(
403
- body["data"] as JSONObject,
422
+ dataInBody as JSONObject,
404
423
  ) as PartialEntity<TBaseModel>;
405
424
 
406
425
  delete (item as any)["_id"];
407
426
  delete (item as any)["createdAt"];
408
427
  delete (item as any)["updatedAt"];
409
428
 
429
+ /*
430
+ * An update that carries no columns writes nothing. Saying 200 to that is
431
+ * the same lie in a different shape, so ask for at least one field.
432
+ */
433
+ if (Object.keys(item).length === 0) {
434
+ throw new BadDataException(
435
+ 'No fields to update. Please include at least one field to update in the "data" object of the request body.',
436
+ );
437
+ }
438
+
410
439
  const numberOfDocsAffected: number = await this.service.updateOneById({
411
440
  id: new ObjectID(objectIdString),
412
441
  data: item,
@@ -21,8 +21,9 @@ import {
21
21
  DEFAULT_LIMIT,
22
22
  LIMIT_PER_PROJECT,
23
23
  } from "../../Types/Database/LimitMax";
24
+ import BadDataException from "../../Types/Exception/BadDataException";
24
25
  import BadRequestException from "../../Types/Exception/BadRequestException";
25
- import { JSONObject } from "../../Types/JSON";
26
+ import { JSONObject, JSONValue } from "../../Types/JSON";
26
27
  import JSONFunctions from "../../Types/JSONFunctions";
27
28
  import ObjectID from "../../Types/ObjectID";
28
29
  import { UserPermission } from "../../Types/Permission";
@@ -542,10 +543,43 @@ export default class BaseAnalyticsAPI<
542
543
  const objectId: ObjectID = new ObjectID(req.params["id"] as string);
543
544
  const objectIdString: string = objectId.toString();
544
545
  const body: JSONObject = req.body;
546
+ const dataInBody: JSONValue | undefined = body["data"];
547
+
548
+ /*
549
+ * Same contract as BaseAPI.updateItem: the payload has to be wrapped as
550
+ * { "data": { ...columns... } }. Reject anything else here rather than
551
+ * letting an empty model reach the service.
552
+ */
553
+ if (
554
+ !dataInBody ||
555
+ typeof dataInBody !== "object" ||
556
+ Array.isArray(dataInBody)
557
+ ) {
558
+ throw new BadDataException(
559
+ 'Invalid request body. The update payload should be an object of the form { "data": { ...fields to update... } }.',
560
+ );
561
+ }
562
+
563
+ /*
564
+ * Count the fields on the raw payload, not on the model: an analytics
565
+ * model instance always carries its own internal properties, so
566
+ * Object.keys() on it is never empty.
567
+ */
568
+ const fieldsToUpdate: Array<string> = Object.keys(
569
+ dataInBody as JSONObject,
570
+ ).filter((key: string) => {
571
+ return key !== "_id" && key !== "createdAt" && key !== "updatedAt";
572
+ });
573
+
574
+ if (fieldsToUpdate.length === 0) {
575
+ throw new BadDataException(
576
+ 'No fields to update. Please include at least one field to update in the "data" object of the request body.',
577
+ );
578
+ }
545
579
 
546
580
  const item: TAnalyticsDataModel =
547
581
  AnalyticsDataModel.fromJSON<TAnalyticsDataModel>(
548
- body["data"] as JSONObject,
582
+ dataInBody as JSONObject,
549
583
  this.entityType,
550
584
  ) as TAnalyticsDataModel;
551
585
 
@@ -11,6 +11,37 @@ import BadDataException from "../../Types/Exception/BadDataException";
11
11
  import NotAuthorizedException from "../../Types/Exception/NotAuthorizedException";
12
12
 
13
13
  export default class CommonAPI {
14
+ /*
15
+ * Custom (non-CRUD) endpoints whose path carries only a resource id give
16
+ * getUserMiddleware no way to learn the project except the `tenantid`
17
+ * header. ModelAPI attaches that header to every request it makes, but a
18
+ * custom route reached with a raw API.post/API.get gets none unless the call
19
+ * site adds ModelAPI.getCommonHeaders() itself. When a caller forgets it,
20
+ * the request still reaches the handler — just with no tenant permissions —
21
+ * and the eventual tenant-scoped read fails as "You do not have permissions
22
+ * to read <model>", which reads like a missing role when it is really a
23
+ * missing header. Assert the scope up front so the caller gets the real
24
+ * cause.
25
+ *
26
+ * This deliberately checks the tenant only, not the user: API-key callers
27
+ * are authenticated by ProjectMiddleware and carry tenant permissions
28
+ * without ever setting `userId`. Use assertAuthenticatedProjectMember when
29
+ * an endpoint must additionally be a logged-in human member.
30
+ */
31
+ public static assertTenantScoped(
32
+ databaseProps: DatabaseCommonInteractionProps,
33
+ ): ObjectID {
34
+ const projectId: ObjectID | undefined = databaseProps.tenantId;
35
+
36
+ if (!projectId) {
37
+ throw new BadDataException(
38
+ "Project ID is required. Please pass the project ID in the 'tenantid' header.",
39
+ );
40
+ }
41
+
42
+ return projectId;
43
+ }
44
+
14
45
  /*
15
46
  * getUserMiddleware lets unauthenticated requests through as "public" and
16
47
  * takes the tenant id from a caller-supplied header — custom endpoints
@@ -40,6 +71,32 @@ export default class CommonAPI {
40
71
  return projectId;
41
72
  }
42
73
 
74
+ /*
75
+ * assertAuthenticatedProjectMember only proves the caller belongs to the
76
+ * project it *claimed* in the `tenantid` header — it never looks at the
77
+ * resource the path names. A custom route that then reads or mutates that
78
+ * resource as root must also confirm the resource's own projectId is the
79
+ * project the caller was authorized for, otherwise a member of project A
80
+ * reaches project B's resource id just by sending their own header.
81
+ *
82
+ * A resource that does not exist (or carries no projectId) is rejected the
83
+ * same way, so the endpoint cannot be used to confirm which ids exist in
84
+ * other projects.
85
+ */
86
+ public static assertResourceBelongsToProject(data: {
87
+ resourceProjectId: ObjectID | undefined | null;
88
+ projectId: ObjectID;
89
+ }): void {
90
+ if (
91
+ !data.resourceProjectId ||
92
+ data.resourceProjectId.toString() !== data.projectId.toString()
93
+ ) {
94
+ throw new NotAuthorizedException(
95
+ "You are not authorized to access this project's data.",
96
+ );
97
+ }
98
+ }
99
+
43
100
  @CaptureSpan()
44
101
  public static async getDatabaseCommonInteractionProps(
45
102
  req: ExpressRequest,
@@ -2,6 +2,9 @@ import Incident from "../../Models/DatabaseModels/Incident";
2
2
  import File from "../../Models/DatabaseModels/File";
3
3
  import NotFoundException from "../../Types/Exception/NotFoundException";
4
4
  import BadDataException from "../../Types/Exception/BadDataException";
5
+ import DatabaseCommonInteractionPropsUtil, {
6
+ PermissionType,
7
+ } from "../../Types/BaseDatabase/DatabaseCommonInteractionPropsUtil";
5
8
  import ObjectID from "../../Types/ObjectID";
6
9
  import IncidentService, {
7
10
  Service as IncidentServiceType,
@@ -22,7 +25,7 @@ import IncidentAIContextBuilder, {
22
25
  IncidentContextData,
23
26
  } from "../Utils/AI/IncidentAIContextBuilder";
24
27
  import JSONFunctions from "../../Types/JSONFunctions";
25
- import Permission from "../../Types/Permission";
28
+ import Permission, { UserPermission } from "../../Types/Permission";
26
29
 
27
30
  export default class IncidentAPI extends BaseAPI<
28
31
  Incident,
@@ -163,21 +166,33 @@ export default class IncidentAPI extends BaseAPI<
163
166
  const props: DatabaseCommonInteractionProps =
164
167
  await CommonAPI.getDatabaseCommonInteractionProps(req);
165
168
 
166
- // Verify user has permission to edit the incident
167
- const permissions: Array<Permission> | undefined = props
168
- .userTenantAccessPermission?.["permissions"] as
169
- | Array<Permission>
170
- | undefined;
171
-
172
- const hasPermission: boolean = permissions
173
- ? permissions.some((p: Permission) => {
174
- return (
175
- p === Permission.ProjectOwner ||
176
- p === Permission.ProjectAdmin ||
177
- p === Permission.EditProjectIncident
178
- );
179
- })
180
- : false;
169
+ CommonAPI.assertTenantScoped(props);
170
+
171
+ /*
172
+ * Read through getUserPermissions(Allow) rather than off
173
+ * userTenantAccessPermission directly. That dictionary is keyed by project
174
+ * id and its entries hold GRANTS AND DENIALS together, discriminated only
175
+ * by isBlockPermission, so the previous
176
+ * `userTenantAccessPermission["permissions"]` read was always undefined
177
+ * and denied every caller who was not a master admin. Mapping the array
178
+ * raw would swing the other way and count a team's explicit block
179
+ * entry for one of these permissions as a grant of it.
180
+ */
181
+ const permissions: Array<Permission> =
182
+ DatabaseCommonInteractionPropsUtil.getUserPermissions(
183
+ props,
184
+ PermissionType.Allow,
185
+ ).map((userPermission: UserPermission) => {
186
+ return userPermission.permission;
187
+ });
188
+
189
+ const hasPermission: boolean = permissions.some((p: Permission) => {
190
+ return (
191
+ p === Permission.ProjectOwner ||
192
+ p === Permission.ProjectAdmin ||
193
+ p === Permission.EditProjectIncident
194
+ );
195
+ });
181
196
 
182
197
  if (!hasPermission && !props.isMasterAdmin) {
183
198
  throw new BadDataException(
@@ -271,23 +286,35 @@ export default class IncidentAPI extends BaseAPI<
271
286
  const props: DatabaseCommonInteractionProps =
272
287
  await CommonAPI.getDatabaseCommonInteractionProps(req);
273
288
 
274
- // Verify user has permission to edit the incident
275
- const permissions: Array<Permission> | undefined = props
276
- .userTenantAccessPermission?.["permissions"] as
277
- | Array<Permission>
278
- | undefined;
279
-
280
- const hasPermission: boolean = permissions
281
- ? permissions.some((p: Permission) => {
282
- return (
283
- p === Permission.ProjectOwner ||
284
- p === Permission.ProjectAdmin ||
285
- p === Permission.EditProjectIncident ||
286
- p === Permission.CreateIncidentInternalNote ||
287
- p === Permission.CreateIncidentPublicNote
288
- );
289
- })
290
- : false;
289
+ CommonAPI.assertTenantScoped(props);
290
+
291
+ /*
292
+ * Read through getUserPermissions(Allow) rather than off
293
+ * userTenantAccessPermission directly. That dictionary is keyed by project
294
+ * id and its entries hold GRANTS AND DENIALS together, discriminated only
295
+ * by isBlockPermission, so the previous
296
+ * `userTenantAccessPermission["permissions"]` read was always undefined
297
+ * and denied every caller who was not a master admin. Mapping the array
298
+ * raw would swing the other way and count a team's explicit block
299
+ * entry for one of these permissions as a grant of it.
300
+ */
301
+ const permissions: Array<Permission> =
302
+ DatabaseCommonInteractionPropsUtil.getUserPermissions(
303
+ props,
304
+ PermissionType.Allow,
305
+ ).map((userPermission: UserPermission) => {
306
+ return userPermission.permission;
307
+ });
308
+
309
+ const hasPermission: boolean = permissions.some((p: Permission) => {
310
+ return (
311
+ p === Permission.ProjectOwner ||
312
+ p === Permission.ProjectAdmin ||
313
+ p === Permission.EditProjectIncident ||
314
+ p === Permission.CreateIncidentInternalNote ||
315
+ p === Permission.CreateIncidentPublicNote
316
+ );
317
+ });
291
318
 
292
319
  if (!hasPermission && !props.isMasterAdmin) {
293
320
  throw new BadDataException(
@@ -1,6 +1,9 @@
1
1
  import IncidentEpisode from "../../Models/DatabaseModels/IncidentEpisode";
2
2
  import BadDataException from "../../Types/Exception/BadDataException";
3
3
  import NotFoundException from "../../Types/Exception/NotFoundException";
4
+ import DatabaseCommonInteractionPropsUtil, {
5
+ PermissionType,
6
+ } from "../../Types/BaseDatabase/DatabaseCommonInteractionPropsUtil";
4
7
  import ObjectID from "../../Types/ObjectID";
5
8
  import IncidentEpisodeService, {
6
9
  Service as IncidentEpisodeServiceType,
@@ -21,7 +24,7 @@ import IncidentEpisodeAIContextBuilder, {
21
24
  } from "../Utils/AI/IncidentEpisodeAIContextBuilder";
22
25
  import { AIGenerationContext } from "../Utils/AI/IncidentAIContextBuilder";
23
26
  import JSONFunctions from "../../Types/JSONFunctions";
24
- import Permission from "../../Types/Permission";
27
+ import Permission, { UserPermission } from "../../Types/Permission";
25
28
 
26
29
  export default class IncidentEpisodeAPI extends BaseAPI<
27
30
  IncidentEpisode,
@@ -67,21 +70,33 @@ export default class IncidentEpisodeAPI extends BaseAPI<
67
70
  const props: DatabaseCommonInteractionProps =
68
71
  await CommonAPI.getDatabaseCommonInteractionProps(req);
69
72
 
70
- // Verify user has permission to edit the episode
71
- const permissions: Array<Permission> | undefined = props
72
- .userTenantAccessPermission?.["permissions"] as
73
- | Array<Permission>
74
- | undefined;
75
-
76
- const hasPermission: boolean = permissions
77
- ? permissions.some((p: Permission) => {
78
- return (
79
- p === Permission.ProjectOwner ||
80
- p === Permission.ProjectAdmin ||
81
- p === Permission.EditIncidentEpisode
82
- );
83
- })
84
- : false;
73
+ CommonAPI.assertTenantScoped(props);
74
+
75
+ /*
76
+ * Read through getUserPermissions(Allow) rather than off
77
+ * userTenantAccessPermission directly. That dictionary is keyed by project
78
+ * id and its entries hold GRANTS AND DENIALS together, discriminated only
79
+ * by isBlockPermission, so the previous
80
+ * `userTenantAccessPermission["permissions"]` read was always undefined
81
+ * and denied every caller who was not a master admin. Mapping the array
82
+ * raw would swing the other way and count a team's explicit block
83
+ * entry for one of these permissions as a grant of it.
84
+ */
85
+ const permissions: Array<Permission> =
86
+ DatabaseCommonInteractionPropsUtil.getUserPermissions(
87
+ props,
88
+ PermissionType.Allow,
89
+ ).map((userPermission: UserPermission) => {
90
+ return userPermission.permission;
91
+ });
92
+
93
+ const hasPermission: boolean = permissions.some((p: Permission) => {
94
+ return (
95
+ p === Permission.ProjectOwner ||
96
+ p === Permission.ProjectAdmin ||
97
+ p === Permission.EditIncidentEpisode
98
+ );
99
+ });
85
100
 
86
101
  if (!hasPermission && !props.isMasterAdmin) {
87
102
  throw new BadDataException(
@@ -9,6 +9,8 @@ import {
9
9
  } from "../Utils/Express";
10
10
  import Response from "../Utils/Response";
11
11
  import BaseAPI from "./BaseAPI";
12
+ import CommonAPI from "./CommonAPI";
13
+ import DatabaseCommonInteractionProps from "../../Types/BaseDatabase/DatabaseCommonInteractionProps";
12
14
  import Monitor from "../../Models/DatabaseModels/Monitor";
13
15
  import ObjectID from "../../Types/ObjectID";
14
16
 
@@ -21,10 +23,38 @@ export default class MonitorAPI extends BaseAPI<Monitor, MonitorServiceType> {
21
23
  UserMiddleware.getUserMiddleware,
22
24
  async (req: ExpressRequest, res: ExpressResponse, next: NextFunction) => {
23
25
  try {
26
+ const databaseProps: DatabaseCommonInteractionProps =
27
+ await CommonAPI.getDatabaseCommonInteractionProps(req);
28
+
29
+ /*
30
+ * getUserMiddleware lets unauthenticated requests through as
31
+ * "public", and refreshMonitorCurrentStatus reads and writes the
32
+ * monitor as root. Require an authenticated member of the
33
+ * monitor's own project — the caller-supplied tenant says nothing
34
+ * about which project the monitor id in the path belongs to.
35
+ */
36
+ const projectId: ObjectID =
37
+ CommonAPI.assertAuthenticatedProjectMember(databaseProps);
38
+
24
39
  const monitorId: ObjectID = new ObjectID(
25
40
  req.params["monitorId"] as string,
26
41
  );
27
42
 
43
+ const monitor: Monitor | null = await MonitorService.findOneById({
44
+ id: monitorId,
45
+ select: {
46
+ projectId: true,
47
+ },
48
+ props: {
49
+ isRoot: true,
50
+ },
51
+ });
52
+
53
+ CommonAPI.assertResourceBelongsToProject({
54
+ resourceProjectId: monitor?.projectId,
55
+ projectId: projectId,
56
+ });
57
+
28
58
  await MonitorService.refreshMonitorCurrentStatus(monitorId);
29
59
  return Response.sendEmptySuccessResponse(req, res);
30
60
  } catch (e) {
@@ -61,6 +61,8 @@ export default class MonitorTemplateAPI extends BaseAPI<
61
61
  const props: DatabaseCommonInteractionProps =
62
62
  await CommonAPI.getDatabaseCommonInteractionProps(req);
63
63
 
64
+ CommonAPI.assertTenantScoped(props);
65
+
64
66
  const fields: Array<string> | undefined = readSyncFields(req);
65
67
 
66
68
  const result: SyncLinkedMonitorsResult =
@@ -98,6 +100,8 @@ export default class MonitorTemplateAPI extends BaseAPI<
98
100
  const props: DatabaseCommonInteractionProps =
99
101
  await CommonAPI.getDatabaseCommonInteractionProps(req);
100
102
 
103
+ CommonAPI.assertTenantScoped(props);
104
+
101
105
  const fields: Array<string> | undefined = readSyncFields(req);
102
106
 
103
107
  await MonitorTemplateService.syncToMonitor({
@@ -133,6 +137,8 @@ export default class MonitorTemplateAPI extends BaseAPI<
133
137
  const props: DatabaseCommonInteractionProps =
134
138
  await CommonAPI.getDatabaseCommonInteractionProps(req);
135
139
 
140
+ CommonAPI.assertTenantScoped(props);
141
+
136
142
  await MonitorTemplateService.linkMonitor({
137
143
  monitorTemplateId,
138
144
  monitorId,
@@ -165,6 +171,8 @@ export default class MonitorTemplateAPI extends BaseAPI<
165
171
  const props: DatabaseCommonInteractionProps =
166
172
  await CommonAPI.getDatabaseCommonInteractionProps(req);
167
173
 
174
+ CommonAPI.assertTenantScoped(props);
175
+
168
176
  await MonitorTemplateService.unlinkMonitor({
169
177
  monitorTemplateId,
170
178
  monitorId,