@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
@@ -2,6 +2,9 @@ import UserMiddleware from "../Middleware/UserAuthorization";
2
2
  import ProbeService, {
3
3
  Service as ProbeServiceType,
4
4
  } from "../Services/ProbeService";
5
+ import Query from "../Types/Database/Query";
6
+ import Select from "../Types/Database/Select";
7
+ import Sort from "../Types/Database/Sort";
5
8
  import {
6
9
  ExpressRequest,
7
10
  ExpressResponse,
@@ -9,10 +12,48 @@ import {
9
12
  } from "../Utils/Express";
10
13
  import Response from "../Utils/Response";
11
14
  import BaseAPI from "./BaseAPI";
12
- import LIMIT_MAX from "../../Types/Database/LimitMax";
15
+ import MultiSearch from "../../Types/BaseDatabase/MultiSearch";
16
+ import {
17
+ DEFAULT_LIMIT,
18
+ LIMIT_PER_PROJECT,
19
+ } from "../../Types/Database/LimitMax";
20
+ import Dictionary from "../../Types/Dictionary";
21
+ import BadDataException from "../../Types/Exception/BadDataException";
22
+ import BadRequestException from "../../Types/Exception/BadRequestException";
23
+ import { JSONObject, JSONValue } from "../../Types/JSON";
24
+ import JSONFunctions from "../../Types/JSONFunctions";
13
25
  import PositiveNumber from "../../Types/PositiveNumber";
14
26
  import Probe from "../../Models/DatabaseModels/Probe";
15
27
 
28
+ // What a caller that asks for no fields in particular gets back.
29
+ const DEFAULT_GLOBAL_PROBE_SELECT: Select<Probe> = {
30
+ name: true,
31
+ description: true,
32
+ lastAlive: true,
33
+ iconFileId: true,
34
+ connectionStatus: true,
35
+ // The monitor create form pre-selects the auto-enabled probes.
36
+ shouldAutoEnableProbeOnNewMonitors: true,
37
+ };
38
+
39
+ /*
40
+ * Global probes are not project rows, so this endpoint has to read them as
41
+ * root - which means none of the usual per-column permission checks run.
42
+ * Every field a caller may select, filter or sort on is therefore listed
43
+ * here, and nothing else is reachable: `key` in particular is a probe's
44
+ * shared secret, and a root-privileged query on it would be an oracle for
45
+ * reading it back one character at a time.
46
+ */
47
+ const GLOBAL_PROBE_FIELDS: Array<string> = [
48
+ ...Object.keys(DEFAULT_GLOBAL_PROBE_SELECT),
49
+ "_id",
50
+ /*
51
+ * Readable, but not something a caller can steer: the query below pins it
52
+ * to true whatever the caller sent.
53
+ */
54
+ "isGlobalProbe",
55
+ ];
56
+
16
57
  export default class ProbeAPI extends BaseAPI<Probe, ProbeServiceType> {
17
58
  public constructor() {
18
59
  super(Probe, ProbeService);
@@ -22,31 +63,72 @@ export default class ProbeAPI extends BaseAPI<Probe, ProbeServiceType> {
22
63
  UserMiddleware.getUserMiddleware,
23
64
  async (req: ExpressRequest, res: ExpressResponse, next: NextFunction) => {
24
65
  try {
66
+ const body: JSONObject = (req.body as JSONObject) || {};
67
+
68
+ const skip: PositiveNumber = new PositiveNumber(
69
+ ProbeAPI.getPaginationValue(req, "skip", 0),
70
+ );
71
+
72
+ const limit: PositiveNumber = new PositiveNumber(
73
+ ProbeAPI.getPaginationValue(req, "limit", DEFAULT_LIMIT),
74
+ );
75
+
76
+ if (limit.toNumber() > LIMIT_PER_PROJECT) {
77
+ throw new BadRequestException(
78
+ "Limit should be less than " + LIMIT_PER_PROJECT,
79
+ );
80
+ }
81
+
82
+ if (skip.toNumber() < 0) {
83
+ throw new BadRequestException(
84
+ "Skip should be greater than or equal to 0",
85
+ );
86
+ }
87
+
88
+ if (limit.toNumber() <= 0) {
89
+ throw new BadRequestException("Limit should be greater than 0");
90
+ }
91
+
92
+ const query: Query<Probe> = {
93
+ ...ProbeAPI.getQuery(body["query"] as JSONObject),
94
+ /*
95
+ * Last, so a caller cannot widen the read past the global probes
96
+ * by sending isGlobalProbe themselves.
97
+ */
98
+ isGlobalProbe: true,
99
+ };
100
+
101
+ const select: Select<Probe> = ProbeAPI.getSelect(
102
+ body["select"] as JSONObject,
103
+ );
104
+
105
+ const sort: Sort<Probe> = ProbeAPI.getSort(
106
+ body["sort"] as JSONObject,
107
+ );
108
+
25
109
  const probes: Array<Probe> = await ProbeService.findBy({
26
- query: {
27
- isGlobalProbe: true,
28
- },
29
- select: {
30
- name: true,
31
- description: true,
32
- lastAlive: true,
33
- iconFileId: true,
34
- connectionStatus: true,
35
- // The monitor create form pre-selects the auto-enabled probes.
36
- shouldAutoEnableProbeOnNewMonitors: true,
110
+ query,
111
+ select,
112
+ sort,
113
+ props: {
114
+ isRoot: true,
37
115
  },
116
+ skip,
117
+ limit,
118
+ });
119
+
120
+ const count: PositiveNumber = await ProbeService.countBy({
121
+ query,
38
122
  props: {
39
123
  isRoot: true,
40
124
  },
41
- skip: 0,
42
- limit: LIMIT_MAX,
43
125
  });
44
126
 
45
127
  return Response.sendEntityArrayResponse(
46
128
  req,
47
129
  res,
48
130
  probes,
49
- new PositiveNumber(probes.length),
131
+ count,
50
132
  Probe,
51
133
  );
52
134
  } catch (err) {
@@ -55,4 +137,103 @@ export default class ProbeAPI extends BaseAPI<Probe, ProbeServiceType> {
55
137
  },
56
138
  );
57
139
  }
140
+
141
+ /*
142
+ * skip/limit arrive as query params from ModelAPI.getList and in the body
143
+ * from anything hand-rolled, so both are read - same precedence as
144
+ * BaseAPI.getList.
145
+ */
146
+ private static getPaginationValue(
147
+ req: ExpressRequest,
148
+ key: "skip" | "limit",
149
+ defaultValue: number,
150
+ ): number {
151
+ if (req.query && req.query[key]) {
152
+ return parseInt(req.query[key] as string, 10) || defaultValue;
153
+ }
154
+
155
+ if (req.body && (req.body as JSONObject)[key] !== undefined) {
156
+ return (
157
+ parseInt((req.body as JSONObject)[key] as string, 10) || defaultValue
158
+ );
159
+ }
160
+
161
+ return defaultValue;
162
+ }
163
+
164
+ private static getQuery(query: JSONObject | undefined): Query<Probe> {
165
+ const deserialized: JSONObject = JSONFunctions.deserialize(
166
+ query as JSONObject,
167
+ );
168
+
169
+ for (const key in deserialized) {
170
+ const value: JSONValue = deserialized[key] as JSONValue;
171
+
172
+ /*
173
+ * MultiSearch is the free-text search operator. Its key is synthetic -
174
+ * the columns it reads are the ones it carries - so those are what get
175
+ * checked against the allow-list.
176
+ */
177
+ if (value instanceof MultiSearch) {
178
+ for (const field of value.fields) {
179
+ if (!GLOBAL_PROBE_FIELDS.includes(field)) {
180
+ throw new BadDataException(
181
+ `Global probes cannot be searched on ${field}.`,
182
+ );
183
+ }
184
+ }
185
+
186
+ continue;
187
+ }
188
+
189
+ if (!GLOBAL_PROBE_FIELDS.includes(key)) {
190
+ throw new BadDataException(
191
+ `Global probes cannot be filtered on ${key}.`,
192
+ );
193
+ }
194
+ }
195
+
196
+ return deserialized as Query<Probe>;
197
+ }
198
+
199
+ private static getSelect(select: JSONObject | undefined): Select<Probe> {
200
+ const requested: Dictionary<boolean> = {};
201
+
202
+ for (const key in select) {
203
+ if (!GLOBAL_PROBE_FIELDS.includes(key) || !select[key]) {
204
+ continue;
205
+ }
206
+
207
+ /*
208
+ * Coerced rather than copied: every selectable field here is a scalar,
209
+ * so a nested (relation) select on one of them is not something the
210
+ * caller gets to ask for.
211
+ */
212
+ requested[key] = true;
213
+ }
214
+
215
+ /*
216
+ * A caller that asks for nothing gets what this endpoint returned before
217
+ * it honoured select at all.
218
+ */
219
+ if (Object.keys(requested).length === 0) {
220
+ return { ...DEFAULT_GLOBAL_PROBE_SELECT };
221
+ }
222
+
223
+ return requested as Select<Probe>;
224
+ }
225
+
226
+ private static getSort(sort: JSONObject | undefined): Sort<Probe> {
227
+ const deserialized: JSONObject = JSONFunctions.deserialize(
228
+ sort as JSONObject,
229
+ );
230
+
231
+ for (const key in deserialized) {
232
+ if (!GLOBAL_PROBE_FIELDS.includes(key)) {
233
+ throw new BadDataException(`Global probes cannot be sorted on ${key}.`);
234
+ }
235
+ }
236
+
237
+ return deserialized as Sort<Probe>;
238
+ }
58
239
  }
@@ -1,4 +1,5 @@
1
1
  import { IsBillingEnabled } from "../EnvironmentConfig";
2
+ import MasterAdminAuthorization from "../Middleware/MasterAdminAuthorization";
2
3
  import UserMiddleware from "../Middleware/UserAuthorization";
3
4
  import ProjectService, {
4
5
  ProjectService as ProjectServiceType,
@@ -13,6 +14,7 @@ import {
13
14
  NextFunction,
14
15
  OneUptimeRequest,
15
16
  } from "../Utils/Express";
17
+ import JSONWebToken from "../Utils/JsonWebToken";
16
18
  import Response from "../Utils/Response";
17
19
  import BaseAPI from "./BaseAPI";
18
20
  import BillingService from "../Services/BillingService";
@@ -24,9 +26,10 @@ import Project from "../../Models/DatabaseModels/Project";
24
26
  import Reseller from "../../Models/DatabaseModels/Reseller";
25
27
  import TeamMember from "../../Models/DatabaseModels/TeamMember";
26
28
  import BadDataException from "../../Types/Exception/BadDataException";
29
+ import OneUptimeDate from "../../Types/Date";
27
30
  import Permission, { UserPermission } from "../../Types/Permission";
28
31
  import ObjectID from "../../Types/ObjectID";
29
- import { JSONObject } from "../../Types/JSON";
32
+ import { JSONObject, JSONValue } from "../../Types/JSON";
30
33
 
31
34
  export default class ProjectAPI extends BaseAPI<Project, ProjectServiceType> {
32
35
  public constructor() {
@@ -134,6 +137,81 @@ export default class ProjectAPI extends BaseAPI<Project, ProjectServiceType> {
134
137
  },
135
138
  );
136
139
 
140
+ /*
141
+ * Extends a project's trial. Master-admin only: this hands out free
142
+ * service and moves the customer's next invoice, so it is deliberately not
143
+ * reachable with project-level billing permissions - only OneUptime staff
144
+ * acting from the Admin Dashboard can call it.
145
+ */
146
+ this.router.put(
147
+ `${new this.entityType().getCrudApiPath()?.toString()}/:id/extend-trial`,
148
+ MasterAdminAuthorization.isAuthorizedMasterAdminMiddleware,
149
+ async (req: ExpressRequest, res: ExpressResponse, next: NextFunction) => {
150
+ try {
151
+ if (!IsBillingEnabled) {
152
+ throw new BadDataException(
153
+ "Billing is not enabled for this server",
154
+ );
155
+ }
156
+
157
+ const projectId: ObjectID = new ObjectID(req.params["id"] as string);
158
+
159
+ const body: JSONObject = (req.body as JSONObject) || {};
160
+ const data: JSONObject = (body["data"] as JSONObject) || {};
161
+ const trialEndsAtValue: JSONValue = data["trialEndsAt"];
162
+
163
+ if (!trialEndsAtValue) {
164
+ throw new BadDataException(
165
+ "Trial end date is required to extend the trial",
166
+ );
167
+ }
168
+
169
+ /*
170
+ * OneUptimeDate.fromString only parses strings and Dates - anything
171
+ * else comes back as its own error text, not a Date - so reject a
172
+ * non-string body value here rather than letting it through.
173
+ */
174
+ if (typeof trialEndsAtValue !== "string") {
175
+ throw new BadDataException("Trial end date is not a valid date");
176
+ }
177
+
178
+ const trialEndsAt: Date = OneUptimeDate.fromString(trialEndsAtValue);
179
+
180
+ if (isNaN(trialEndsAt.getTime())) {
181
+ throw new BadDataException("Trial end date is not a valid date");
182
+ }
183
+
184
+ /*
185
+ * The master admin middleware verifies the token but does not put
186
+ * the decoded payload on the request, so read it again here - who
187
+ * granted the extension is the only audit trail this action has.
188
+ */
189
+ let extendedByUserId: ObjectID | undefined = undefined;
190
+
191
+ try {
192
+ const accessToken: string | undefined =
193
+ UserMiddleware.getAccessTokenFromExpressRequest(req);
194
+
195
+ if (accessToken) {
196
+ extendedByUserId = JSONWebToken.decode(accessToken).userId;
197
+ }
198
+ } catch {
199
+ // Only used for the log line - never block the extension on it.
200
+ }
201
+
202
+ await ProjectService.extendTrial({
203
+ projectId: projectId,
204
+ trialEndsAt: trialEndsAt,
205
+ extendedByUserId: extendedByUserId,
206
+ });
207
+
208
+ return Response.sendEmptySuccessResponse(req, res);
209
+ } catch (err) {
210
+ next(err);
211
+ }
212
+ },
213
+ );
214
+
137
215
  /*
138
216
  * This API lists all the projects where user is its team member.
139
217
  * This API is usually used to show project selector dropdown in the UI
@@ -1,6 +1,9 @@
1
1
  import ScheduledMaintenance from "../../Models/DatabaseModels/ScheduledMaintenance";
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 ScheduledMaintenanceService, {
6
9
  Service as ScheduledMaintenanceServiceType,
@@ -21,7 +24,7 @@ import ScheduledMaintenanceAIContextBuilder, {
21
24
  ScheduledMaintenanceContextData,
22
25
  } from "../Utils/AI/ScheduledMaintenanceAIContextBuilder";
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 ScheduledMaintenanceAPI extends BaseAPI<
27
30
  ScheduledMaintenance,
@@ -68,23 +71,35 @@ export default class ScheduledMaintenanceAPI extends BaseAPI<
68
71
  const props: DatabaseCommonInteractionProps =
69
72
  await CommonAPI.getDatabaseCommonInteractionProps(req);
70
73
 
71
- // Verify user has permission
72
- const permissions: Array<Permission> | undefined = props
73
- .userTenantAccessPermission?.["permissions"] as
74
- | Array<Permission>
75
- | undefined;
76
-
77
- const hasPermission: boolean = permissions
78
- ? permissions.some((p: Permission) => {
79
- return (
80
- p === Permission.ProjectOwner ||
81
- p === Permission.ProjectAdmin ||
82
- p === Permission.EditProjectScheduledMaintenance ||
83
- p === Permission.CreateScheduledMaintenanceInternalNote ||
84
- p === Permission.CreateScheduledMaintenancePublicNote
85
- );
86
- })
87
- : false;
74
+ CommonAPI.assertTenantScoped(props);
75
+
76
+ /*
77
+ * Read through getUserPermissions(Allow) rather than off
78
+ * userTenantAccessPermission directly. That dictionary is keyed by project
79
+ * id and its entries hold GRANTS AND DENIALS together, discriminated only
80
+ * by isBlockPermission, so the previous
81
+ * `userTenantAccessPermission["permissions"]` read was always undefined
82
+ * and denied every caller who was not a master admin. Mapping the array
83
+ * raw would swing the other way and count a team's explicit block
84
+ * entry for one of these permissions as a grant of it.
85
+ */
86
+ const permissions: Array<Permission> =
87
+ DatabaseCommonInteractionPropsUtil.getUserPermissions(
88
+ props,
89
+ PermissionType.Allow,
90
+ ).map((userPermission: UserPermission) => {
91
+ return userPermission.permission;
92
+ });
93
+
94
+ const hasPermission: boolean = permissions.some((p: Permission) => {
95
+ return (
96
+ p === Permission.ProjectOwner ||
97
+ p === Permission.ProjectAdmin ||
98
+ p === Permission.EditProjectScheduledMaintenance ||
99
+ p === Permission.CreateScheduledMaintenanceInternalNote ||
100
+ p === Permission.CreateScheduledMaintenancePublicNote
101
+ );
102
+ });
88
103
 
89
104
  if (!hasPermission && !props.isMasterAdmin) {
90
105
  throw new BadDataException(
@@ -85,6 +85,7 @@ import StatusPageOIDC from "../../Models/DatabaseModels/StatusPageOidc";
85
85
  import StatusPageSubscriber from "../../Models/DatabaseModels/StatusPageSubscriber";
86
86
  import StatusPageEventType from "../../Types/StatusPage/StatusPageEventType";
87
87
  import StatusPageResourceUptimeUtil from "../../Utils/StatusPage/ResourceUptime";
88
+ import StatusPageGroupTreeUtil from "../../Utils/StatusPage/GroupTree";
88
89
  import UptimePrecision from "../../Types/StatusPage/UptimePrecision";
89
90
  import { Green } from "../../Types/BrandColors";
90
91
  import UptimeUtil, { UptimeWindow } from "../../Utils/Uptime/UptimeUtil";
@@ -1225,6 +1226,7 @@ export default class StatusPageAPI extends BaseAPI<
1225
1226
 
1226
1227
  type StatusPageGroupUptime = {
1227
1228
  statusPageGroupId: ObjectID | null;
1229
+ parentStatusPageGroupId: ObjectID | null;
1228
1230
  uptimePercent: number | null;
1229
1231
  statusPageResourceUptimes: Array<ResourceUptime>;
1230
1232
  statusPageGroupName: string | null;
@@ -1244,6 +1246,8 @@ export default class StatusPageAPI extends BaseAPI<
1244
1246
  data && data.statusPageGroup
1245
1247
  ? data.statusPageGroup?.id
1246
1248
  : null,
1249
+ parentStatusPageGroupId:
1250
+ data.statusPageGroup?.parentStatusPageGroupId || null,
1247
1251
  uptimePercent: null,
1248
1252
  statusPageResourceUptimes: [],
1249
1253
  statusPageGroupName: data.statusPageGroup?.name || null,
@@ -1382,43 +1386,6 @@ export default class StatusPageAPI extends BaseAPI<
1382
1386
  }
1383
1387
  }
1384
1388
 
1385
- if (group?.showUptimePercent) {
1386
- // calculate uptime percent for the group.
1387
- const avgUptimePercent: number =
1388
- UptimeUtil.calculateAvgUptimePercentage({
1389
- uptimePercentages: groupUptime.statusPageResourceUptimes
1390
- .filter((resource: ResourceUptime) => {
1391
- return resource.uptimePercent !== null;
1392
- })
1393
- .map((resource: ResourceUptime) => {
1394
- return resource.uptimePercent || 0;
1395
- }),
1396
- precision:
1397
- group.uptimePercentPrecision ||
1398
- UptimePrecision.ONE_DECIMAL,
1399
- });
1400
-
1401
- groupUptime.uptimePercent = avgUptimePercent;
1402
- }
1403
-
1404
- if (group?.showCurrentStatus) {
1405
- const currentStatuses: Array<MonitorStatus> =
1406
- groupUptime.statusPageResourceUptimes
1407
- .filter((resourceUptime: ResourceUptime) => {
1408
- return resourceUptime.currentStatus !== null;
1409
- })
1410
- .map((resourceUptime: ResourceUptime) => {
1411
- return resourceUptime.currentStatus!;
1412
- });
1413
-
1414
- const worstStatus: MonitorStatus | null =
1415
- StatusPageResourceUptimeUtil.getWorstMonitorStatus({
1416
- monitorStatuses: currentStatuses,
1417
- });
1418
-
1419
- groupUptime.currentStatus = worstStatus;
1420
- }
1421
-
1422
1389
  return groupUptime;
1423
1390
  };
1424
1391
 
@@ -1430,6 +1397,75 @@ export default class StatusPageAPI extends BaseAPI<
1430
1397
  );
1431
1398
  }
1432
1399
 
1400
+ /*
1401
+ * Groups nest, so a group's own uptime % / current status has to
1402
+ * cover every resource in its subtree, not just the resources
1403
+ * attached directly to it. statusPageResourceUptimes stays the
1404
+ * group's own resources - the nesting is reported through
1405
+ * parentStatusPageGroupId so callers can rebuild the tree.
1406
+ */
1407
+ const resourceUptimesByGroupId: Dictionary<Array<ResourceUptime>> =
1408
+ {};
1409
+
1410
+ for (const groupUptime of groupUptimes) {
1411
+ resourceUptimesByGroupId[
1412
+ groupUptime.statusPageGroupId?.toString() || ""
1413
+ ] = groupUptime.statusPageResourceUptimes;
1414
+ }
1415
+
1416
+ for (const group of statusPageGroups) {
1417
+ const groupUptime: StatusPageGroupUptime | undefined =
1418
+ groupUptimes.find((item: StatusPageGroupUptime) => {
1419
+ return (
1420
+ item.statusPageGroupId?.toString() === group.id?.toString()
1421
+ );
1422
+ });
1423
+
1424
+ if (!groupUptime) {
1425
+ continue;
1426
+ }
1427
+
1428
+ const resourceUptimesInSubtree: Array<ResourceUptime> =
1429
+ StatusPageGroupTreeUtil.getGroupAndDescendants({
1430
+ statusPageGroup: group,
1431
+ statusPageGroups: statusPageGroups,
1432
+ }).flatMap((groupInSubtree: StatusPageGroup) => {
1433
+ return (
1434
+ resourceUptimesByGroupId[
1435
+ groupInSubtree.id?.toString() || ""
1436
+ ] || []
1437
+ );
1438
+ });
1439
+
1440
+ if (group.showUptimePercent) {
1441
+ groupUptime.uptimePercent =
1442
+ UptimeUtil.calculateAvgUptimePercentage({
1443
+ uptimePercentages: resourceUptimesInSubtree
1444
+ .filter((resource: ResourceUptime) => {
1445
+ return resource.uptimePercent !== null;
1446
+ })
1447
+ .map((resource: ResourceUptime) => {
1448
+ return resource.uptimePercent || 0;
1449
+ }),
1450
+ precision:
1451
+ group.uptimePercentPrecision || UptimePrecision.ONE_DECIMAL,
1452
+ });
1453
+ }
1454
+
1455
+ if (group.showCurrentStatus) {
1456
+ groupUptime.currentStatus =
1457
+ StatusPageResourceUptimeUtil.getWorstMonitorStatus({
1458
+ monitorStatuses: resourceUptimesInSubtree
1459
+ .filter((resourceUptime: ResourceUptime) => {
1460
+ return resourceUptime.currentStatus !== null;
1461
+ })
1462
+ .map((resourceUptime: ResourceUptime) => {
1463
+ return resourceUptime.currentStatus!;
1464
+ }),
1465
+ });
1466
+ }
1467
+ }
1468
+
1433
1469
  return Response.sendJsonObjectResponse(req, res, {
1434
1470
  statusPageResourceUptimes: [
1435
1471
  ...getUptimeByStatusPageGroup({ statusPageGroup: null })
@@ -4920,6 +4956,7 @@ export default class StatusPageAPI extends BaseAPI<
4920
4956
  columnAxisLabel: true,
4921
4957
  rowAxisValues: true,
4922
4958
  columnAxisValues: true,
4959
+ parentStatusPageGroupId: true,
4923
4960
  },
4924
4961
  sort: {
4925
4962
  order: SortOrder.Ascending,
@@ -29,12 +29,42 @@ export default class WorkspaceNotificationRuleAPI extends BaseAPI<
29
29
  const databaseProps: DatabaseCommonInteractionProps =
30
30
  await CommonAPI.getDatabaseCommonInteractionProps(req);
31
31
 
32
+ /*
33
+ * getUserMiddleware lets unauthenticated requests through as
34
+ * "public", and testRule loads the rule as root and then posts a
35
+ * test message into that project's Slack / Teams channels — it can
36
+ * even create channels. Require an authenticated member of the
37
+ * project, and of the rule's own project at that: testRule takes
38
+ * the project from the rule it loaded, so the caller-supplied
39
+ * tenant alone proves nothing about the rule id in the path.
40
+ */
41
+ const projectId: ObjectID =
42
+ CommonAPI.assertAuthenticatedProjectMember(databaseProps);
43
+
44
+ const ruleId: ObjectID = new ObjectID(
45
+ req.params["workspaceNotifcationRuleId"] as string,
46
+ );
47
+
48
+ const rule: WorkspaceNotificationRule | null =
49
+ await this.service.findOneById({
50
+ id: ruleId,
51
+ select: {
52
+ projectId: true,
53
+ },
54
+ props: {
55
+ isRoot: true,
56
+ },
57
+ });
58
+
59
+ CommonAPI.assertResourceBelongsToProject({
60
+ resourceProjectId: rule?.projectId,
61
+ projectId: projectId,
62
+ });
63
+
32
64
  await this.service.testRule({
33
- ruleId: new ObjectID(
34
- req.params["workspaceNotifcationRuleId"] as string,
35
- ),
65
+ ruleId: ruleId,
36
66
  props: databaseProps,
37
- projectId: databaseProps.tenantId!,
67
+ projectId: projectId,
38
68
  testByUserId: databaseProps.userId!,
39
69
  });
40
70
 
@@ -0,0 +1,13 @@
1
+ import { MigrationInterface, QueryRunner } from "typeorm";
2
+
3
+ export class AddColumnsToTableView1785241000000 implements MigrationInterface {
4
+ public name: string = "AddColumnsToTableView1785241000000";
5
+
6
+ public async up(queryRunner: QueryRunner): Promise<void> {
7
+ await queryRunner.query(`ALTER TABLE "TableView" ADD "columns" jsonb`);
8
+ }
9
+
10
+ public async down(queryRunner: QueryRunner): Promise<void> {
11
+ await queryRunner.query(`ALTER TABLE "TableView" DROP COLUMN "columns"`);
12
+ }
13
+ }