@oneuptime/common 11.0.1 → 11.0.2

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 (341) hide show
  1. package/Models/DatabaseModels/Alert.ts +110 -0
  2. package/Models/DatabaseModels/CephCluster.ts +964 -0
  3. package/Models/DatabaseModels/CephClusterLabelRule.ts +514 -0
  4. package/Models/DatabaseModels/CephClusterOwnerRule.ts +596 -0
  5. package/Models/DatabaseModels/CephClusterOwnerTeam.ts +487 -0
  6. package/Models/DatabaseModels/CephClusterOwnerUser.ts +486 -0
  7. package/Models/DatabaseModels/CephResource.ts +809 -0
  8. package/Models/DatabaseModels/Host.ts +64 -0
  9. package/Models/DatabaseModels/Incident.ts +110 -0
  10. package/Models/DatabaseModels/Index.ts +24 -0
  11. package/Models/DatabaseModels/ProxmoxCluster.ts +943 -0
  12. package/Models/DatabaseModels/ProxmoxClusterLabelRule.ts +514 -0
  13. package/Models/DatabaseModels/ProxmoxClusterOwnerRule.ts +596 -0
  14. package/Models/DatabaseModels/ProxmoxClusterOwnerTeam.ts +487 -0
  15. package/Models/DatabaseModels/ProxmoxClusterOwnerUser.ts +486 -0
  16. package/Models/DatabaseModels/ProxmoxResource.ts +726 -0
  17. package/Models/DatabaseModels/ScheduledMaintenance.ts +110 -0
  18. package/Server/API/BillingInvoiceAPI.ts +47 -7
  19. package/Server/API/CephResourceAPI.ts +134 -0
  20. package/Server/API/DashboardAPI.ts +46 -0
  21. package/Server/API/ProjectAPI.ts +15 -0
  22. package/Server/API/ProxmoxResourceAPI.ts +132 -0
  23. package/Server/API/ResellerPlanAPI.ts +17 -0
  24. package/Server/Infrastructure/GlobalCache.ts +8 -2
  25. package/Server/Infrastructure/Postgres/SchemaMigrations/1781500000000-AddProxmoxAndCephClusterTables.ts +163 -0
  26. package/Server/Infrastructure/Postgres/SchemaMigrations/1781600000000-AddProxmoxCephV2Columns.ts +211 -0
  27. package/Server/Infrastructure/Postgres/SchemaMigrations/1781600000001-AddProxmoxCephActivityAndRules.ts +590 -0
  28. package/Server/Infrastructure/Postgres/SchemaMigrations/1781700000000-AddProxmoxCephV3Columns.ts +64 -0
  29. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +8 -0
  30. package/Server/Infrastructure/Redis.ts +40 -12
  31. package/Server/Services/AnalyticsDatabaseService.ts +1 -1
  32. package/Server/Services/BillingService.ts +109 -21
  33. package/Server/Services/CephClusterLabelRuleEngineService.ts +200 -0
  34. package/Server/Services/CephClusterLabelRuleService.ts +14 -0
  35. package/Server/Services/CephClusterOwnerRuleEngineService.ts +218 -0
  36. package/Server/Services/CephClusterOwnerRuleService.ts +14 -0
  37. package/Server/Services/CephClusterOwnerTeamService.ts +10 -0
  38. package/Server/Services/CephClusterOwnerUserService.ts +10 -0
  39. package/Server/Services/CephClusterService.ts +401 -0
  40. package/Server/Services/CephResourceService.ts +383 -0
  41. package/Server/Services/CloudResourceService.ts +11 -3
  42. package/Server/Services/DockerHostService.ts +11 -3
  43. package/Server/Services/ExceptionAggregationService.ts +2 -0
  44. package/Server/Services/HostService.ts +11 -3
  45. package/Server/Services/Index.ts +24 -0
  46. package/Server/Services/KubernetesClusterService.ts +11 -3
  47. package/Server/Services/LogAggregationService.ts +2 -0
  48. package/Server/Services/MetricAggregationService.ts +2 -0
  49. package/Server/Services/OpenTelemetryIngestService.ts +36 -0
  50. package/Server/Services/ProxmoxClusterLabelRuleEngineService.ts +204 -0
  51. package/Server/Services/ProxmoxClusterLabelRuleService.ts +14 -0
  52. package/Server/Services/ProxmoxClusterOwnerRuleEngineService.ts +222 -0
  53. package/Server/Services/ProxmoxClusterOwnerRuleService.ts +14 -0
  54. package/Server/Services/ProxmoxClusterOwnerTeamService.ts +10 -0
  55. package/Server/Services/ProxmoxClusterOwnerUserService.ts +10 -0
  56. package/Server/Services/ProxmoxClusterService.ts +382 -0
  57. package/Server/Services/ProxmoxResourceService.ts +404 -0
  58. package/Server/Services/RumApplicationService.ts +11 -3
  59. package/Server/Services/ServerlessFunctionService.ts +11 -3
  60. package/Server/Services/TelemetryUsageBillingService.ts +41 -3
  61. package/Server/Services/TraceAggregationService.ts +2 -0
  62. package/Server/Types/AnalyticsDatabase/AggregateBy.ts +8 -23
  63. package/Server/Utils/Monitor/MonitorAlert.ts +45 -0
  64. package/Server/Utils/Monitor/MonitorClusterContext.ts +129 -0
  65. package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +344 -4
  66. package/Server/Utils/Monitor/MonitorIncident.ts +130 -7
  67. package/Server/Utils/Monitor/MonitorMaintenanceSuppression.ts +39 -6
  68. package/Server/Utils/Monitor/MonitorTemplateUtil.ts +3 -1
  69. package/Server/Utils/Monitor/SeriesResourceLabels.ts +33 -0
  70. package/Server/Utils/Profiling.ts +37 -2
  71. package/Server/Utils/Telemetry/EntityRegistry.ts +4 -0
  72. package/Server/Utils/Telemetry/ProxmoxCephSnapshotScan.ts +1096 -0
  73. package/Server/Utils/Telemetry/TelemetryEntity.ts +85 -0
  74. package/Server/Utils/Telemetry.ts +8 -19
  75. package/Tests/Server/API/BillingInvoiceAPI.test.ts +194 -0
  76. package/Tests/Server/API/ProjectAPI.test.ts +91 -0
  77. package/Tests/Server/API/ResellerPlanAPI.test.ts +207 -0
  78. package/Tests/Server/Infrastructure/GlobalCache.test.ts +100 -0
  79. package/Tests/Server/Services/BillingService.test.ts +323 -0
  80. package/Tests/Server/Services/CephResourceService.test.ts +264 -0
  81. package/Tests/Server/Services/ProxmoxResourceService.test.ts +326 -0
  82. package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluator.test.ts +322 -0
  83. package/Tests/Server/Utils/Monitor/MonitorMaintenanceSuppression.test.ts +13 -0
  84. package/Tests/Server/Utils/Telemetry/ProxmoxCephSnapshotScan.test.ts +879 -0
  85. package/Tests/Server/Utils/Telemetry/TelemetryEntity.test.ts +196 -0
  86. package/Tests/Types/Monitor/CephAlertTemplates.test.ts +1231 -0
  87. package/Tests/Types/Monitor/ProxmoxAlertTemplates.test.ts +732 -0
  88. package/Tests/Utils/Telemetry/EntityRelationship.test.ts +49 -0
  89. package/Tests/Utils/Telemetry/HeartbeatAvailability.test.ts +423 -0
  90. package/Types/BaseDatabase/AggregationIntervalUtil.ts +74 -0
  91. package/Types/Dashboard/DashboardComponentType.ts +4 -0
  92. package/Types/Dashboard/DashboardComponents/ComponentArgument.ts +2 -0
  93. package/Types/Dashboard/DashboardComponents/DashboardCephOsdListComponent.ts +15 -0
  94. package/Types/Dashboard/DashboardComponents/DashboardCephPoolListComponent.ts +14 -0
  95. package/Types/Dashboard/DashboardComponents/DashboardProxmoxGuestListComponent.ts +17 -0
  96. package/Types/Dashboard/DashboardComponents/DashboardProxmoxNodeListComponent.ts +16 -0
  97. package/Types/Dashboard/DashboardTemplates.ts +446 -0
  98. package/Types/Icon/IconProp.ts +2 -0
  99. package/Types/Monitor/CephAlertTemplates.ts +1647 -0
  100. package/Types/Monitor/CephMetricCatalog.ts +409 -0
  101. package/Types/Monitor/MetricMonitor/MetricMonitorResponse.ts +44 -0
  102. package/Types/Monitor/MonitorStep.ts +64 -0
  103. package/Types/Monitor/MonitorStepCephMonitor.ts +57 -0
  104. package/Types/Monitor/MonitorStepProxmoxMonitor.ts +81 -0
  105. package/Types/Monitor/MonitorType.ts +29 -1
  106. package/Types/Monitor/ProxmoxAlertTemplates.ts +899 -0
  107. package/Types/Monitor/ProxmoxMetricCatalog.ts +382 -0
  108. package/Types/Permission.ts +464 -0
  109. package/Types/Telemetry/EntityType.ts +11 -0
  110. package/Types/Telemetry/ServiceType.ts +2 -0
  111. package/UI/Components/Icon/Icon.tsx +84 -0
  112. package/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.ts +9 -5
  113. package/UI/Utils/Telemetry/Telemetry.ts +16 -21
  114. package/UI/Utils/TelemetryService.ts +7 -3
  115. package/Utils/Dashboard/Components/DashboardCephOsdListComponent.ts +63 -0
  116. package/Utils/Dashboard/Components/DashboardCephPoolListComponent.ts +32 -0
  117. package/Utils/Dashboard/Components/DashboardCephResourceListShared.ts +61 -0
  118. package/Utils/Dashboard/Components/DashboardProxmoxGuestListComponent.ts +69 -0
  119. package/Utils/Dashboard/Components/DashboardProxmoxNodeListComponent.ts +55 -0
  120. package/Utils/Dashboard/Components/DashboardProxmoxResourceListShared.ts +61 -0
  121. package/Utils/Dashboard/Components/Index.ts +28 -0
  122. package/Utils/Telemetry/EntityKey.ts +35 -0
  123. package/Utils/Telemetry/EntityRelationship.ts +6 -0
  124. package/Utils/Telemetry/HeartbeatAvailability.ts +262 -0
  125. package/build/dist/Models/DatabaseModels/Alert.js +108 -0
  126. package/build/dist/Models/DatabaseModels/Alert.js.map +1 -1
  127. package/build/dist/Models/DatabaseModels/CephCluster.js +992 -0
  128. package/build/dist/Models/DatabaseModels/CephCluster.js.map +1 -0
  129. package/build/dist/Models/DatabaseModels/CephClusterLabelRule.js +522 -0
  130. package/build/dist/Models/DatabaseModels/CephClusterLabelRule.js.map +1 -0
  131. package/build/dist/Models/DatabaseModels/CephClusterOwnerRule.js +603 -0
  132. package/build/dist/Models/DatabaseModels/CephClusterOwnerRule.js.map +1 -0
  133. package/build/dist/Models/DatabaseModels/CephClusterOwnerTeam.js +503 -0
  134. package/build/dist/Models/DatabaseModels/CephClusterOwnerTeam.js.map +1 -0
  135. package/build/dist/Models/DatabaseModels/CephClusterOwnerUser.js +502 -0
  136. package/build/dist/Models/DatabaseModels/CephClusterOwnerUser.js.map +1 -0
  137. package/build/dist/Models/DatabaseModels/CephResource.js +846 -0
  138. package/build/dist/Models/DatabaseModels/CephResource.js.map +1 -0
  139. package/build/dist/Models/DatabaseModels/Host.js +63 -0
  140. package/build/dist/Models/DatabaseModels/Host.js.map +1 -1
  141. package/build/dist/Models/DatabaseModels/Incident.js +108 -0
  142. package/build/dist/Models/DatabaseModels/Incident.js.map +1 -1
  143. package/build/dist/Models/DatabaseModels/Index.js +24 -0
  144. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  145. package/build/dist/Models/DatabaseModels/ProxmoxCluster.js +967 -0
  146. package/build/dist/Models/DatabaseModels/ProxmoxCluster.js.map +1 -0
  147. package/build/dist/Models/DatabaseModels/ProxmoxClusterLabelRule.js +522 -0
  148. package/build/dist/Models/DatabaseModels/ProxmoxClusterLabelRule.js.map +1 -0
  149. package/build/dist/Models/DatabaseModels/ProxmoxClusterOwnerRule.js +603 -0
  150. package/build/dist/Models/DatabaseModels/ProxmoxClusterOwnerRule.js.map +1 -0
  151. package/build/dist/Models/DatabaseModels/ProxmoxClusterOwnerTeam.js +503 -0
  152. package/build/dist/Models/DatabaseModels/ProxmoxClusterOwnerTeam.js.map +1 -0
  153. package/build/dist/Models/DatabaseModels/ProxmoxClusterOwnerUser.js +502 -0
  154. package/build/dist/Models/DatabaseModels/ProxmoxClusterOwnerUser.js.map +1 -0
  155. package/build/dist/Models/DatabaseModels/ProxmoxResource.js +761 -0
  156. package/build/dist/Models/DatabaseModels/ProxmoxResource.js.map +1 -0
  157. package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js +108 -0
  158. package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js.map +1 -1
  159. package/build/dist/Server/API/BillingInvoiceAPI.js +35 -5
  160. package/build/dist/Server/API/BillingInvoiceAPI.js.map +1 -1
  161. package/build/dist/Server/API/CephResourceAPI.js +98 -0
  162. package/build/dist/Server/API/CephResourceAPI.js.map +1 -0
  163. package/build/dist/Server/API/DashboardAPI.js +46 -0
  164. package/build/dist/Server/API/DashboardAPI.js.map +1 -1
  165. package/build/dist/Server/API/ProjectAPI.js +11 -0
  166. package/build/dist/Server/API/ProjectAPI.js.map +1 -1
  167. package/build/dist/Server/API/ProxmoxResourceAPI.js +95 -0
  168. package/build/dist/Server/API/ProxmoxResourceAPI.js.map +1 -0
  169. package/build/dist/Server/API/ResellerPlanAPI.js +17 -3
  170. package/build/dist/Server/API/ResellerPlanAPI.js.map +1 -1
  171. package/build/dist/Server/Infrastructure/GlobalCache.js +7 -2
  172. package/build/dist/Server/Infrastructure/GlobalCache.js.map +1 -1
  173. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1781500000000-AddProxmoxAndCephClusterTables.js +76 -0
  174. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1781500000000-AddProxmoxAndCephClusterTables.js.map +1 -0
  175. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1781600000000-AddProxmoxCephV2Columns.js +108 -0
  176. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1781600000000-AddProxmoxCephV2Columns.js.map +1 -0
  177. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1781600000001-AddProxmoxCephActivityAndRules.js +253 -0
  178. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1781600000001-AddProxmoxCephActivityAndRules.js.map +1 -0
  179. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1781700000000-AddProxmoxCephV3Columns.js +43 -0
  180. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1781700000000-AddProxmoxCephV3Columns.js.map +1 -0
  181. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +8 -0
  182. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  183. package/build/dist/Server/Infrastructure/Redis.js +31 -8
  184. package/build/dist/Server/Infrastructure/Redis.js.map +1 -1
  185. package/build/dist/Server/Services/AnalyticsDatabaseService.js +1 -1
  186. package/build/dist/Server/Services/AnalyticsDatabaseService.js.map +1 -1
  187. package/build/dist/Server/Services/BillingService.js +85 -23
  188. package/build/dist/Server/Services/BillingService.js.map +1 -1
  189. package/build/dist/Server/Services/CephClusterLabelRuleEngineService.js +166 -0
  190. package/build/dist/Server/Services/CephClusterLabelRuleEngineService.js.map +1 -0
  191. package/build/dist/Server/Services/CephClusterLabelRuleService.js +13 -0
  192. package/build/dist/Server/Services/CephClusterLabelRuleService.js.map +1 -0
  193. package/build/dist/Server/Services/CephClusterOwnerRuleEngineService.js +186 -0
  194. package/build/dist/Server/Services/CephClusterOwnerRuleEngineService.js.map +1 -0
  195. package/build/dist/Server/Services/CephClusterOwnerRuleService.js +13 -0
  196. package/build/dist/Server/Services/CephClusterOwnerRuleService.js.map +1 -0
  197. package/build/dist/Server/Services/CephClusterOwnerTeamService.js +9 -0
  198. package/build/dist/Server/Services/CephClusterOwnerTeamService.js.map +1 -0
  199. package/build/dist/Server/Services/CephClusterOwnerUserService.js +9 -0
  200. package/build/dist/Server/Services/CephClusterOwnerUserService.js.map +1 -0
  201. package/build/dist/Server/Services/CephClusterService.js +353 -0
  202. package/build/dist/Server/Services/CephClusterService.js.map +1 -0
  203. package/build/dist/Server/Services/CephResourceService.js +257 -0
  204. package/build/dist/Server/Services/CephResourceService.js.map +1 -0
  205. package/build/dist/Server/Services/CloudResourceService.js +10 -2
  206. package/build/dist/Server/Services/CloudResourceService.js.map +1 -1
  207. package/build/dist/Server/Services/DockerHostService.js +10 -2
  208. package/build/dist/Server/Services/DockerHostService.js.map +1 -1
  209. package/build/dist/Server/Services/ExceptionAggregationService.js +2 -0
  210. package/build/dist/Server/Services/ExceptionAggregationService.js.map +1 -1
  211. package/build/dist/Server/Services/HostService.js +10 -2
  212. package/build/dist/Server/Services/HostService.js.map +1 -1
  213. package/build/dist/Server/Services/Index.js +24 -0
  214. package/build/dist/Server/Services/Index.js.map +1 -1
  215. package/build/dist/Server/Services/KubernetesClusterService.js +10 -2
  216. package/build/dist/Server/Services/KubernetesClusterService.js.map +1 -1
  217. package/build/dist/Server/Services/LogAggregationService.js +2 -0
  218. package/build/dist/Server/Services/LogAggregationService.js.map +1 -1
  219. package/build/dist/Server/Services/MetricAggregationService.js +2 -0
  220. package/build/dist/Server/Services/MetricAggregationService.js.map +1 -1
  221. package/build/dist/Server/Services/OpenTelemetryIngestService.js +37 -7
  222. package/build/dist/Server/Services/OpenTelemetryIngestService.js.map +1 -1
  223. package/build/dist/Server/Services/ProxmoxClusterLabelRuleEngineService.js +166 -0
  224. package/build/dist/Server/Services/ProxmoxClusterLabelRuleEngineService.js.map +1 -0
  225. package/build/dist/Server/Services/ProxmoxClusterLabelRuleService.js +13 -0
  226. package/build/dist/Server/Services/ProxmoxClusterLabelRuleService.js.map +1 -0
  227. package/build/dist/Server/Services/ProxmoxClusterOwnerRuleEngineService.js +186 -0
  228. package/build/dist/Server/Services/ProxmoxClusterOwnerRuleEngineService.js.map +1 -0
  229. package/build/dist/Server/Services/ProxmoxClusterOwnerRuleService.js +13 -0
  230. package/build/dist/Server/Services/ProxmoxClusterOwnerRuleService.js.map +1 -0
  231. package/build/dist/Server/Services/ProxmoxClusterOwnerTeamService.js +9 -0
  232. package/build/dist/Server/Services/ProxmoxClusterOwnerTeamService.js.map +1 -0
  233. package/build/dist/Server/Services/ProxmoxClusterOwnerUserService.js +9 -0
  234. package/build/dist/Server/Services/ProxmoxClusterOwnerUserService.js.map +1 -0
  235. package/build/dist/Server/Services/ProxmoxClusterService.js +337 -0
  236. package/build/dist/Server/Services/ProxmoxClusterService.js.map +1 -0
  237. package/build/dist/Server/Services/ProxmoxResourceService.js +285 -0
  238. package/build/dist/Server/Services/ProxmoxResourceService.js.map +1 -0
  239. package/build/dist/Server/Services/RumApplicationService.js +10 -2
  240. package/build/dist/Server/Services/RumApplicationService.js.map +1 -1
  241. package/build/dist/Server/Services/ServerlessFunctionService.js +10 -2
  242. package/build/dist/Server/Services/ServerlessFunctionService.js.map +1 -1
  243. package/build/dist/Server/Services/TelemetryUsageBillingService.js +30 -3
  244. package/build/dist/Server/Services/TelemetryUsageBillingService.js.map +1 -1
  245. package/build/dist/Server/Services/TraceAggregationService.js +2 -0
  246. package/build/dist/Server/Services/TraceAggregationService.js.map +1 -1
  247. package/build/dist/Server/Types/AnalyticsDatabase/AggregateBy.js +8 -25
  248. package/build/dist/Server/Types/AnalyticsDatabase/AggregateBy.js.map +1 -1
  249. package/build/dist/Server/Utils/Monitor/MonitorAlert.js +36 -0
  250. package/build/dist/Server/Utils/Monitor/MonitorAlert.js.map +1 -1
  251. package/build/dist/Server/Utils/Monitor/MonitorClusterContext.js +90 -0
  252. package/build/dist/Server/Utils/Monitor/MonitorClusterContext.js.map +1 -0
  253. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +228 -4
  254. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
  255. package/build/dist/Server/Utils/Monitor/MonitorIncident.js +103 -8
  256. package/build/dist/Server/Utils/Monitor/MonitorIncident.js.map +1 -1
  257. package/build/dist/Server/Utils/Monitor/MonitorMaintenanceSuppression.js +23 -6
  258. package/build/dist/Server/Utils/Monitor/MonitorMaintenanceSuppression.js.map +1 -1
  259. package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js +3 -1
  260. package/build/dist/Server/Utils/Monitor/MonitorTemplateUtil.js.map +1 -1
  261. package/build/dist/Server/Utils/Monitor/SeriesResourceLabels.js +23 -0
  262. package/build/dist/Server/Utils/Monitor/SeriesResourceLabels.js.map +1 -1
  263. package/build/dist/Server/Utils/Profiling.js +24 -3
  264. package/build/dist/Server/Utils/Profiling.js.map +1 -1
  265. package/build/dist/Server/Utils/Telemetry/EntityRegistry.js +4 -0
  266. package/build/dist/Server/Utils/Telemetry/EntityRegistry.js.map +1 -1
  267. package/build/dist/Server/Utils/Telemetry/ProxmoxCephSnapshotScan.js +854 -0
  268. package/build/dist/Server/Utils/Telemetry/ProxmoxCephSnapshotScan.js.map +1 -0
  269. package/build/dist/Server/Utils/Telemetry/TelemetryEntity.js +62 -0
  270. package/build/dist/Server/Utils/Telemetry/TelemetryEntity.js.map +1 -1
  271. package/build/dist/Server/Utils/Telemetry.js +8 -10
  272. package/build/dist/Server/Utils/Telemetry.js.map +1 -1
  273. package/build/dist/Types/BaseDatabase/AggregationIntervalUtil.js +69 -0
  274. package/build/dist/Types/BaseDatabase/AggregationIntervalUtil.js.map +1 -0
  275. package/build/dist/Types/Dashboard/DashboardComponentType.js +4 -0
  276. package/build/dist/Types/Dashboard/DashboardComponentType.js.map +1 -1
  277. package/build/dist/Types/Dashboard/DashboardComponents/ComponentArgument.js +2 -0
  278. package/build/dist/Types/Dashboard/DashboardComponents/ComponentArgument.js.map +1 -1
  279. package/build/dist/Types/Dashboard/DashboardComponents/DashboardCephOsdListComponent.js +2 -0
  280. package/build/dist/Types/Dashboard/DashboardComponents/DashboardCephOsdListComponent.js.map +1 -0
  281. package/build/dist/Types/Dashboard/DashboardComponents/DashboardCephPoolListComponent.js +2 -0
  282. package/build/dist/Types/Dashboard/DashboardComponents/DashboardCephPoolListComponent.js.map +1 -0
  283. package/build/dist/Types/Dashboard/DashboardComponents/DashboardProxmoxGuestListComponent.js +2 -0
  284. package/build/dist/Types/Dashboard/DashboardComponents/DashboardProxmoxGuestListComponent.js.map +1 -0
  285. package/build/dist/Types/Dashboard/DashboardComponents/DashboardProxmoxNodeListComponent.js +2 -0
  286. package/build/dist/Types/Dashboard/DashboardComponents/DashboardProxmoxNodeListComponent.js.map +1 -0
  287. package/build/dist/Types/Dashboard/DashboardTemplates.js +394 -0
  288. package/build/dist/Types/Dashboard/DashboardTemplates.js.map +1 -1
  289. package/build/dist/Types/Icon/IconProp.js +2 -0
  290. package/build/dist/Types/Icon/IconProp.js.map +1 -1
  291. package/build/dist/Types/Monitor/CephAlertTemplates.js +1379 -0
  292. package/build/dist/Types/Monitor/CephAlertTemplates.js.map +1 -0
  293. package/build/dist/Types/Monitor/CephMetricCatalog.js +353 -0
  294. package/build/dist/Types/Monitor/CephMetricCatalog.js.map +1 -0
  295. package/build/dist/Types/Monitor/MonitorStep.js +46 -0
  296. package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
  297. package/build/dist/Types/Monitor/MonitorStepCephMonitor.js +34 -0
  298. package/build/dist/Types/Monitor/MonitorStepCephMonitor.js.map +1 -0
  299. package/build/dist/Types/Monitor/MonitorStepProxmoxMonitor.js +36 -0
  300. package/build/dist/Types/Monitor/MonitorStepProxmoxMonitor.js.map +1 -0
  301. package/build/dist/Types/Monitor/MonitorType.js +27 -1
  302. package/build/dist/Types/Monitor/MonitorType.js.map +1 -1
  303. package/build/dist/Types/Monitor/ProxmoxAlertTemplates.js +743 -0
  304. package/build/dist/Types/Monitor/ProxmoxAlertTemplates.js.map +1 -0
  305. package/build/dist/Types/Monitor/ProxmoxMetricCatalog.js +320 -0
  306. package/build/dist/Types/Monitor/ProxmoxMetricCatalog.js.map +1 -0
  307. package/build/dist/Types/Permission.js +408 -0
  308. package/build/dist/Types/Permission.js.map +1 -1
  309. package/build/dist/Types/Telemetry/EntityType.js +11 -0
  310. package/build/dist/Types/Telemetry/EntityType.js.map +1 -1
  311. package/build/dist/Types/Telemetry/ServiceType.js +2 -0
  312. package/build/dist/Types/Telemetry/ServiceType.js.map +1 -1
  313. package/build/dist/UI/Components/Icon/Icon.js +33 -0
  314. package/build/dist/UI/Components/Icon/Icon.js.map +1 -1
  315. package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.js +5 -1
  316. package/build/dist/UI/Components/MonitorTemplateVariables/TemplateVariablesCatalog.js.map +1 -1
  317. package/build/dist/UI/Utils/Telemetry/Telemetry.js +11 -10
  318. package/build/dist/UI/Utils/Telemetry/Telemetry.js.map +1 -1
  319. package/build/dist/UI/Utils/TelemetryService.js +5 -2
  320. package/build/dist/UI/Utils/TelemetryService.js.map +1 -1
  321. package/build/dist/Utils/Dashboard/Components/DashboardCephOsdListComponent.js +50 -0
  322. package/build/dist/Utils/Dashboard/Components/DashboardCephOsdListComponent.js.map +1 -0
  323. package/build/dist/Utils/Dashboard/Components/DashboardCephPoolListComponent.js +27 -0
  324. package/build/dist/Utils/Dashboard/Components/DashboardCephPoolListComponent.js.map +1 -0
  325. package/build/dist/Utils/Dashboard/Components/DashboardCephResourceListShared.js +46 -0
  326. package/build/dist/Utils/Dashboard/Components/DashboardCephResourceListShared.js.map +1 -0
  327. package/build/dist/Utils/Dashboard/Components/DashboardProxmoxGuestListComponent.js +55 -0
  328. package/build/dist/Utils/Dashboard/Components/DashboardProxmoxGuestListComponent.js.map +1 -0
  329. package/build/dist/Utils/Dashboard/Components/DashboardProxmoxNodeListComponent.js +42 -0
  330. package/build/dist/Utils/Dashboard/Components/DashboardProxmoxNodeListComponent.js.map +1 -0
  331. package/build/dist/Utils/Dashboard/Components/DashboardProxmoxResourceListShared.js +46 -0
  332. package/build/dist/Utils/Dashboard/Components/DashboardProxmoxResourceListShared.js.map +1 -0
  333. package/build/dist/Utils/Dashboard/Components/Index.js +16 -0
  334. package/build/dist/Utils/Dashboard/Components/Index.js.map +1 -1
  335. package/build/dist/Utils/Telemetry/EntityKey.js +27 -0
  336. package/build/dist/Utils/Telemetry/EntityKey.js.map +1 -1
  337. package/build/dist/Utils/Telemetry/EntityRelationship.js +3 -0
  338. package/build/dist/Utils/Telemetry/EntityRelationship.js.map +1 -1
  339. package/build/dist/Utils/Telemetry/HeartbeatAvailability.js +174 -0
  340. package/build/dist/Utils/Telemetry/HeartbeatAvailability.js.map +1 -0
  341. package/package.json +29 -21
@@ -1,3 +1,4 @@
1
+ import CephCluster from "./CephCluster";
1
2
  import DockerHost from "./DockerHost";
2
3
  import Host from "./Host";
3
4
  import KubernetesCluster from "./KubernetesCluster";
@@ -5,6 +6,7 @@ import Label from "./Label";
5
6
  import Monitor from "./Monitor";
6
7
  import MonitorStatus from "./MonitorStatus";
7
8
  import Project from "./Project";
9
+ import ProxmoxCluster from "./ProxmoxCluster";
8
10
  import ScheduledMaintenanceState from "./ScheduledMaintenanceState";
9
11
  import Service from "./Service";
10
12
  import StatusPage from "./StatusPage";
@@ -652,6 +654,114 @@ export default class ScheduledMaintenance extends BaseModel {
652
654
  })
653
655
  public dockerHosts?: Array<DockerHost> = undefined;
654
656
 
657
+ @ColumnAccessControl({
658
+ create: [
659
+ Permission.ProjectOwner,
660
+ Permission.ProjectAdmin,
661
+ Permission.ProjectMember,
662
+ Permission.ScheduledMaintenanceAdmin,
663
+ Permission.ScheduledMaintenanceMember,
664
+ Permission.CreateProjectScheduledMaintenance,
665
+ ],
666
+ read: [
667
+ Permission.ProjectOwner,
668
+ Permission.ProjectAdmin,
669
+ Permission.ProjectMember,
670
+ Permission.Viewer,
671
+ Permission.ScheduledMaintenanceAdmin,
672
+ Permission.ScheduledMaintenanceMember,
673
+ Permission.ScheduledMaintenanceViewer,
674
+ Permission.ReadProjectScheduledMaintenance,
675
+ ],
676
+ update: [
677
+ Permission.ProjectOwner,
678
+ Permission.ProjectAdmin,
679
+ Permission.ProjectMember,
680
+ Permission.ScheduledMaintenanceAdmin,
681
+ Permission.ScheduledMaintenanceMember,
682
+ Permission.EditProjectScheduledMaintenance,
683
+ ],
684
+ })
685
+ @TableColumn({
686
+ required: false,
687
+ type: TableColumnType.EntityArray,
688
+ modelType: ProxmoxCluster,
689
+ title: "Proxmox Clusters",
690
+ description: "List of Proxmox clusters affected by this event.",
691
+ })
692
+ @ManyToMany(
693
+ () => {
694
+ return ProxmoxCluster;
695
+ },
696
+ { eager: false },
697
+ )
698
+ @JoinTable({
699
+ name: "ScheduledMaintenanceProxmoxCluster",
700
+ inverseJoinColumn: {
701
+ name: "proxmoxClusterId",
702
+ referencedColumnName: "_id",
703
+ },
704
+ joinColumn: {
705
+ name: "scheduledMaintenanceId",
706
+ referencedColumnName: "_id",
707
+ },
708
+ })
709
+ public proxmoxClusters?: Array<ProxmoxCluster> = undefined;
710
+
711
+ @ColumnAccessControl({
712
+ create: [
713
+ Permission.ProjectOwner,
714
+ Permission.ProjectAdmin,
715
+ Permission.ProjectMember,
716
+ Permission.ScheduledMaintenanceAdmin,
717
+ Permission.ScheduledMaintenanceMember,
718
+ Permission.CreateProjectScheduledMaintenance,
719
+ ],
720
+ read: [
721
+ Permission.ProjectOwner,
722
+ Permission.ProjectAdmin,
723
+ Permission.ProjectMember,
724
+ Permission.Viewer,
725
+ Permission.ScheduledMaintenanceAdmin,
726
+ Permission.ScheduledMaintenanceMember,
727
+ Permission.ScheduledMaintenanceViewer,
728
+ Permission.ReadProjectScheduledMaintenance,
729
+ ],
730
+ update: [
731
+ Permission.ProjectOwner,
732
+ Permission.ProjectAdmin,
733
+ Permission.ProjectMember,
734
+ Permission.ScheduledMaintenanceAdmin,
735
+ Permission.ScheduledMaintenanceMember,
736
+ Permission.EditProjectScheduledMaintenance,
737
+ ],
738
+ })
739
+ @TableColumn({
740
+ required: false,
741
+ type: TableColumnType.EntityArray,
742
+ modelType: CephCluster,
743
+ title: "Ceph Clusters",
744
+ description: "List of Ceph clusters affected by this event.",
745
+ })
746
+ @ManyToMany(
747
+ () => {
748
+ return CephCluster;
749
+ },
750
+ { eager: false },
751
+ )
752
+ @JoinTable({
753
+ name: "ScheduledMaintenanceCephCluster",
754
+ inverseJoinColumn: {
755
+ name: "cephClusterId",
756
+ referencedColumnName: "_id",
757
+ },
758
+ joinColumn: {
759
+ name: "scheduledMaintenanceId",
760
+ referencedColumnName: "_id",
761
+ },
762
+ })
763
+ public cephClusters?: Array<CephCluster> = undefined;
764
+
655
765
  @ColumnAccessControl({
656
766
  create: [
657
767
  Permission.ProjectOwner,
@@ -41,7 +41,9 @@ export default class UserAPI extends BaseAPI<
41
41
  }
42
42
 
43
43
  if (req.body["projectId"]) {
44
- throw new BadDataException("projectId is required in request body");
44
+ throw new BadDataException(
45
+ "projectId should not be passed in the request body. The project is resolved from the tenantid header.",
46
+ );
45
47
  }
46
48
 
47
49
  const userPermissions: Array<UserPermission> = (
@@ -102,20 +104,57 @@ export default class UserAPI extends BaseAPI<
102
104
  throw new BadDataException("Invoice ID not found");
103
105
  }
104
106
 
105
- if (!item.paymentProviderCustomerId) {
106
- throw new BadDataException("Customer ID not found");
107
+ /*
108
+ * Never trust the customer id from the request body — always
109
+ * charge the authenticated project's own Stripe customer. A
110
+ * mismatch means the caller is trying to pay against another
111
+ * tenant's customer.
112
+ */
113
+ if (
114
+ item.paymentProviderCustomerId &&
115
+ item.paymentProviderCustomerId !== project.paymentProviderCustomerId
116
+ ) {
117
+ throw new BadDataException(
118
+ "Customer ID does not belong to this project",
119
+ );
120
+ }
121
+
122
+ // the invoice must belong to this project.
123
+ const billingInvoice: BillingInvoice | null =
124
+ await BillingInvoiceService.findOneBy({
125
+ query: {
126
+ projectId: project.id!,
127
+ paymentProviderInvoiceId: item.paymentProviderInvoiceId,
128
+ },
129
+ select: {
130
+ _id: true,
131
+ },
132
+ props: {
133
+ isRoot: true,
134
+ /*
135
+ * skip onBeforeFind: it requires props.tenantId and would
136
+ * re-sync all invoices from Stripe on every pay attempt.
137
+ * The query above is already scoped to the project.
138
+ */
139
+ ignoreHooks: true,
140
+ },
141
+ });
142
+
143
+ if (!billingInvoice) {
144
+ throw new BadDataException("Invoice not found for this project");
107
145
  }
146
+
108
147
  let invoice: Invoice | null = null;
109
148
 
110
149
  try {
111
150
  invoice = await BillingService.payInvoice(
112
- item.paymentProviderCustomerId!,
113
- item.paymentProviderInvoiceId!,
151
+ project.paymentProviderCustomerId,
152
+ item.paymentProviderInvoiceId,
114
153
  );
115
154
  } catch (err) {
116
155
  invoice = await BillingService.getInvoice(
117
- item.paymentProviderCustomerId!,
118
- item.paymentProviderInvoiceId!,
156
+ project.paymentProviderCustomerId,
157
+ item.paymentProviderInvoiceId,
119
158
  );
120
159
 
121
160
  // check if this invoice needs more authentication like 3ds secure.
@@ -142,6 +181,7 @@ export default class UserAPI extends BaseAPI<
142
181
 
143
182
  await this.service.updateOneBy({
144
183
  query: {
184
+ projectId: project.id!,
145
185
  paymentProviderInvoiceId: invoice.id!,
146
186
  },
147
187
  props: {
@@ -0,0 +1,134 @@
1
+ import CephResource from "../../Models/DatabaseModels/CephResource";
2
+ import CephCluster from "../../Models/DatabaseModels/CephCluster";
3
+ import BadDataException from "../../Types/Exception/BadDataException";
4
+ import ObjectID from "../../Types/ObjectID";
5
+ import CephResourceService, {
6
+ CephInventorySummary,
7
+ Service as CephResourceServiceType,
8
+ } from "../Services/CephResourceService";
9
+ import CephClusterService from "../Services/CephClusterService";
10
+ import UserMiddleware from "../Middleware/UserAuthorization";
11
+ import Response from "../Utils/Response";
12
+ import BaseAPI from "./BaseAPI";
13
+ import {
14
+ ExpressRequest,
15
+ ExpressResponse,
16
+ NextFunction,
17
+ } from "../Utils/Express";
18
+ import CommonAPI from "./CommonAPI";
19
+ import DatabaseCommonInteractionProps from "../../Types/BaseDatabase/DatabaseCommonInteractionProps";
20
+ import NotFoundException from "../../Types/Exception/NotFoundException";
21
+ import { JSONObject } from "../../Types/JSON";
22
+
23
+ /*
24
+ * ------------------------------------------------------------------
25
+ * CephResourceAPI
26
+ *
27
+ * Augments the auto-generated CRUD router with a single custom
28
+ * endpoint the Ceph layout/overview pages use to fetch sidebar badge
29
+ * counts in one round-trip:
30
+ *
31
+ * POST /ceph-resource/inventory-summary/:clusterId
32
+ *
33
+ * The standard CRUD endpoints (list / get) are still registered by
34
+ * BaseAPI; the UI uses them via ModelAPI for list/detail reads.
35
+ * Write endpoints reject (@TableAccessControl create/update/delete
36
+ * = []); ingest writes go through CephResourceService as root.
37
+ * ------------------------------------------------------------------
38
+ */
39
+ export default class CephResourceAPI extends BaseAPI<
40
+ CephResource,
41
+ CephResourceServiceType
42
+ > {
43
+ public constructor() {
44
+ super(CephResource, CephResourceService);
45
+
46
+ this.router.post(
47
+ `${new this.entityType()
48
+ .getCrudApiPath()
49
+ ?.toString()}/inventory-summary/:clusterId`,
50
+ UserMiddleware.getUserMiddleware,
51
+ async (req: ExpressRequest, res: ExpressResponse, next: NextFunction) => {
52
+ try {
53
+ await this.getInventorySummary(req, res);
54
+ } catch (err) {
55
+ next(err);
56
+ }
57
+ },
58
+ );
59
+ }
60
+
61
+ /*
62
+ * Cluster + auth resolution for the cluster-scoped sub-route.
63
+ * Returns the (projectId, cephClusterId) tuple after enforcing the
64
+ * standard ACL chain. Throws NotFound when the cluster is missing
65
+ * or the caller lacks read access (indistinguishable on purpose).
66
+ */
67
+ private async resolveClusterForRequest(req: ExpressRequest): Promise<{
68
+ projectId: ObjectID;
69
+ cephClusterId: ObjectID;
70
+ }> {
71
+ const clusterIdParam: string | undefined = req.params["clusterId"];
72
+ if (!clusterIdParam) {
73
+ throw new BadDataException("Cluster ID is required");
74
+ }
75
+
76
+ let cephClusterId: ObjectID;
77
+ try {
78
+ cephClusterId = new ObjectID(clusterIdParam);
79
+ } catch {
80
+ throw new BadDataException("Invalid Cluster ID");
81
+ }
82
+
83
+ const props: DatabaseCommonInteractionProps =
84
+ await CommonAPI.getDatabaseCommonInteractionProps(req);
85
+
86
+ const cluster: CephCluster | null = await CephClusterService.findOneById({
87
+ id: cephClusterId,
88
+ select: {
89
+ _id: true,
90
+ projectId: true,
91
+ },
92
+ props,
93
+ });
94
+
95
+ if (!cluster || !cluster.projectId) {
96
+ throw new NotFoundException("Ceph Cluster not found");
97
+ }
98
+
99
+ return {
100
+ projectId: cluster.projectId,
101
+ cephClusterId,
102
+ };
103
+ }
104
+
105
+ private async getInventorySummary(
106
+ req: ExpressRequest,
107
+ res: ExpressResponse,
108
+ ): Promise<void> {
109
+ const { projectId, cephClusterId } =
110
+ await this.resolveClusterForRequest(req);
111
+
112
+ const summary: CephInventorySummary =
113
+ await this.service.getInventorySummary({
114
+ projectId,
115
+ cephClusterId,
116
+ });
117
+
118
+ const responseBody: JSONObject = {
119
+ countsByKind: summary.countsByKind as unknown as JSONObject,
120
+ // Convenience fields so the UI doesn't have to repeat COALESCE:
121
+ osdCount: summary.countsByKind["Osd"] || 0,
122
+ poolCount: summary.countsByKind["Pool"] || 0,
123
+ monCount: summary.countsByKind["Mon"] || 0,
124
+ mgrCount: summary.countsByKind["Mgr"] || 0,
125
+ mdsCount: summary.countsByKind["Mds"] || 0,
126
+ rgwCount: summary.countsByKind["Rgw"] || 0,
127
+ osdUpCount: summary.osdUpCount,
128
+ osdInCount: summary.osdInCount,
129
+ monInQuorumCount: summary.monInQuorumCount,
130
+ };
131
+
132
+ return Response.sendJsonObjectResponse(req, res, responseBody);
133
+ }
134
+ }
@@ -45,6 +45,8 @@ import Host from "../../Models/DatabaseModels/Host";
45
45
  import KubernetesResource from "../../Models/DatabaseModels/KubernetesResource";
46
46
  import DockerHost from "../../Models/DatabaseModels/DockerHost";
47
47
  import DockerResource from "../../Models/DatabaseModels/DockerResource";
48
+ import ProxmoxResource from "../../Models/DatabaseModels/ProxmoxResource";
49
+ import CephResource from "../../Models/DatabaseModels/CephResource";
48
50
  import Span from "../../Models/AnalyticsModels/Span";
49
51
  import Log from "../../Models/AnalyticsModels/Log";
50
52
  import IncidentService from "../Services/IncidentService";
@@ -54,6 +56,8 @@ import HostService from "../Services/HostService";
54
56
  import KubernetesResourceService from "../Services/KubernetesResourceService";
55
57
  import DockerHostService from "../Services/DockerHostService";
56
58
  import DockerResourceService from "../Services/DockerResourceService";
59
+ import ProxmoxResourceService from "../Services/ProxmoxResourceService";
60
+ import CephResourceService from "../Services/CephResourceService";
57
61
  import SpanService from "../Services/SpanService";
58
62
  import LogService from "../Services/LogService";
59
63
 
@@ -211,6 +215,48 @@ const PUBLIC_DASHBOARD_RESOURCES: Record<
211
215
  dockerHost: { name: true },
212
216
  },
213
217
  },
218
+ "proxmox-resource": {
219
+ modelType: ProxmoxResource,
220
+ service: ProxmoxResourceService,
221
+ select: {
222
+ _id: true,
223
+ name: true,
224
+ externalId: true,
225
+ kind: true,
226
+ vmid: true,
227
+ guestType: true,
228
+ parentNodeName: true,
229
+ isUp: true,
230
+ haState: true,
231
+ latestCpuPercent: true,
232
+ latestMemoryPercent: true,
233
+ lastSeenAt: true,
234
+ proxmoxClusterId: true,
235
+ proxmoxCluster: { name: true },
236
+ },
237
+ },
238
+ "ceph-resource": {
239
+ modelType: CephResource,
240
+ service: CephResourceService,
241
+ select: {
242
+ _id: true,
243
+ name: true,
244
+ externalId: true,
245
+ kind: true,
246
+ hostname: true,
247
+ deviceClass: true,
248
+ isUp: true,
249
+ isIn: true,
250
+ statBytes: true,
251
+ statBytesUsed: true,
252
+ storedBytes: true,
253
+ maxAvailBytes: true,
254
+ objects: true,
255
+ lastSeenAt: true,
256
+ cephClusterId: true,
257
+ cephCluster: { name: true },
258
+ },
259
+ },
214
260
  span: {
215
261
  modelType: Span,
216
262
  service: SpanService,
@@ -45,6 +45,21 @@ export default class ProjectAPI extends BaseAPI<Project, ProjectServiceType> {
45
45
 
46
46
  const projectId: ObjectID = new ObjectID(req.params["id"] as string);
47
47
 
48
+ /*
49
+ * The permission check below is bound to the authenticated tenant
50
+ * (resolved from the tenantid header), so the project being
51
+ * mutated must be that same tenant — otherwise permissions on one
52
+ * project would authorize changing the plan (and charging the
53
+ * payment method) of another.
54
+ */
55
+ const tenantId: ObjectID | null = this.getTenantId(req);
56
+
57
+ if (!tenantId || tenantId.toString() !== projectId.toString()) {
58
+ throw new BadDataException(
59
+ "Project ID in the URL does not match the project the request is authenticated for",
60
+ );
61
+ }
62
+
48
63
  const body: JSONObject = (req.body as JSONObject) || {};
49
64
  const data: JSONObject = (body["data"] as JSONObject) || {};
50
65
  const paymentProviderPlanId: string | undefined = data[
@@ -0,0 +1,132 @@
1
+ import ProxmoxResource from "../../Models/DatabaseModels/ProxmoxResource";
2
+ import ProxmoxCluster from "../../Models/DatabaseModels/ProxmoxCluster";
3
+ import BadDataException from "../../Types/Exception/BadDataException";
4
+ import ObjectID from "../../Types/ObjectID";
5
+ import ProxmoxResourceService, {
6
+ ProxmoxInventorySummary,
7
+ Service as ProxmoxResourceServiceType,
8
+ } from "../Services/ProxmoxResourceService";
9
+ import ProxmoxClusterService from "../Services/ProxmoxClusterService";
10
+ import UserMiddleware from "../Middleware/UserAuthorization";
11
+ import Response from "../Utils/Response";
12
+ import BaseAPI from "./BaseAPI";
13
+ import {
14
+ ExpressRequest,
15
+ ExpressResponse,
16
+ NextFunction,
17
+ } from "../Utils/Express";
18
+ import CommonAPI from "./CommonAPI";
19
+ import DatabaseCommonInteractionProps from "../../Types/BaseDatabase/DatabaseCommonInteractionProps";
20
+ import NotFoundException from "../../Types/Exception/NotFoundException";
21
+ import { JSONObject } from "../../Types/JSON";
22
+
23
+ /*
24
+ * ------------------------------------------------------------------
25
+ * ProxmoxResourceAPI
26
+ *
27
+ * Augments the auto-generated CRUD router with a single custom
28
+ * endpoint the Proxmox layout/overview pages use to fetch sidebar
29
+ * badge counts in one round-trip:
30
+ *
31
+ * POST /proxmox-resource/inventory-summary/:clusterId
32
+ *
33
+ * The standard CRUD endpoints (list / get) are still registered by
34
+ * BaseAPI; the UI uses them via ModelAPI for list/detail reads.
35
+ * Write endpoints reject (@TableAccessControl create/update/delete
36
+ * = []); ingest writes go through ProxmoxResourceService as root.
37
+ * ------------------------------------------------------------------
38
+ */
39
+ export default class ProxmoxResourceAPI extends BaseAPI<
40
+ ProxmoxResource,
41
+ ProxmoxResourceServiceType
42
+ > {
43
+ public constructor() {
44
+ super(ProxmoxResource, ProxmoxResourceService);
45
+
46
+ this.router.post(
47
+ `${new this.entityType()
48
+ .getCrudApiPath()
49
+ ?.toString()}/inventory-summary/:clusterId`,
50
+ UserMiddleware.getUserMiddleware,
51
+ async (req: ExpressRequest, res: ExpressResponse, next: NextFunction) => {
52
+ try {
53
+ await this.getInventorySummary(req, res);
54
+ } catch (err) {
55
+ next(err);
56
+ }
57
+ },
58
+ );
59
+ }
60
+
61
+ /*
62
+ * Cluster + auth resolution for the cluster-scoped sub-route.
63
+ * Returns the (projectId, proxmoxClusterId) tuple after enforcing
64
+ * the standard ACL chain. Throws NotFound when the cluster is
65
+ * missing or the caller lacks read access (indistinguishable on
66
+ * purpose).
67
+ */
68
+ private async resolveClusterForRequest(req: ExpressRequest): Promise<{
69
+ projectId: ObjectID;
70
+ proxmoxClusterId: ObjectID;
71
+ }> {
72
+ const clusterIdParam: string | undefined = req.params["clusterId"];
73
+ if (!clusterIdParam) {
74
+ throw new BadDataException("Cluster ID is required");
75
+ }
76
+
77
+ let proxmoxClusterId: ObjectID;
78
+ try {
79
+ proxmoxClusterId = new ObjectID(clusterIdParam);
80
+ } catch {
81
+ throw new BadDataException("Invalid Cluster ID");
82
+ }
83
+
84
+ const props: DatabaseCommonInteractionProps =
85
+ await CommonAPI.getDatabaseCommonInteractionProps(req);
86
+
87
+ const cluster: ProxmoxCluster | null =
88
+ await ProxmoxClusterService.findOneById({
89
+ id: proxmoxClusterId,
90
+ select: {
91
+ _id: true,
92
+ projectId: true,
93
+ },
94
+ props,
95
+ });
96
+
97
+ if (!cluster || !cluster.projectId) {
98
+ throw new NotFoundException("Proxmox Cluster not found");
99
+ }
100
+
101
+ return {
102
+ projectId: cluster.projectId,
103
+ proxmoxClusterId,
104
+ };
105
+ }
106
+
107
+ private async getInventorySummary(
108
+ req: ExpressRequest,
109
+ res: ExpressResponse,
110
+ ): Promise<void> {
111
+ const { projectId, proxmoxClusterId } =
112
+ await this.resolveClusterForRequest(req);
113
+
114
+ const summary: ProxmoxInventorySummary =
115
+ await this.service.getInventorySummary({
116
+ projectId,
117
+ proxmoxClusterId,
118
+ });
119
+
120
+ const responseBody: JSONObject = {
121
+ countsByKind: summary.countsByKind as unknown as JSONObject,
122
+ // Convenience fields so the UI doesn't have to repeat COALESCE:
123
+ nodeCount: summary.countsByKind["Node"] || 0,
124
+ guestCount: summary.countsByKind["Guest"] || 0,
125
+ storageCount: summary.countsByKind["Storage"] || 0,
126
+ nodeOnlineCount: summary.nodeOnlineCount,
127
+ guestRunningCount: summary.guestRunningCount,
128
+ };
129
+
130
+ return Response.sendJsonObjectResponse(req, res, responseBody);
131
+ }
132
+ }
@@ -77,6 +77,7 @@ export default class ResellerPlanAPI extends BaseAPI<
77
77
  _id: true,
78
78
  planId: true,
79
79
  reseller: {
80
+ _id: true,
80
81
  resellerId: true,
81
82
  },
82
83
  teamMemberLimit: true,
@@ -98,6 +99,13 @@ export default class ResellerPlanAPI extends BaseAPI<
98
99
  );
99
100
  }
100
101
 
102
+ const resellerObjectId: ObjectID | undefined =
103
+ resellerPlan.reseller?.id || undefined;
104
+
105
+ if (!resellerObjectId) {
106
+ throw new BadDataException("Invalid reseller plan id.");
107
+ }
108
+
101
109
  const licenseKey: string | undefined = req.body.uuid;
102
110
 
103
111
  if (!licenseKey) {
@@ -166,6 +174,12 @@ export default class ResellerPlanAPI extends BaseAPI<
166
174
  const project: Project | null = await ProjectService.findOneBy({
167
175
  query: {
168
176
  resellerLicenseId: licenseKey,
177
+ /*
178
+ * license keys are not globally unique — scope to the
179
+ * authenticated reseller so one reseller cannot modify
180
+ * another reseller's customer project.
181
+ */
182
+ resellerId: resellerObjectId,
169
183
  },
170
184
  select: {
171
185
  _id: true,
@@ -207,6 +221,8 @@ export default class ResellerPlanAPI extends BaseAPI<
207
221
  const project: Project | null = await ProjectService.findOneBy({
208
222
  query: {
209
223
  resellerLicenseId: licenseKey,
224
+ // scope to the authenticated reseller — see enhance_tier.
225
+ resellerId: resellerObjectId,
210
226
  },
211
227
  select: {
212
228
  _id: true,
@@ -226,6 +242,7 @@ export default class ResellerPlanAPI extends BaseAPI<
226
242
  await ProjectService.deleteOneBy({
227
243
  query: {
228
244
  resellerLicenseId: licenseKey,
245
+ resellerId: resellerObjectId,
229
246
  _id: project.id?.toString() as string,
230
247
  },
231
248
  props: {
@@ -164,9 +164,15 @@ export default abstract class GlobalCache {
164
164
  throw new DatabaseNotConnectedException("Cache is not connected");
165
165
  }
166
166
 
167
- await client.set(`${namespace}-${key}`, value);
168
167
  const expiresInSeconds: number =
169
168
  options?.expiresInSeconds ?? OneUptimeDate.getSecondsInDays(30);
170
- await client.expire(`${namespace}-${key}`, expiresInSeconds);
169
+
170
+ /*
171
+ * Atomic SET ... EX — a separate SET followed by EXPIRE can crash
172
+ * in between and leave the key with no TTL. For fence / throttle
173
+ * keys (e.g. otel-maintenance-fence) a TTL-less key never expires
174
+ * and permanently suppresses the work it gates.
175
+ */
176
+ await client.set(`${namespace}-${key}`, value, "EX", expiresInSeconds);
171
177
  }
172
178
  }