@oneuptime/common 13.0.8 → 14.0.0

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 (333) hide show
  1. package/Models/AnalyticsModels/AuditLog.ts +23 -15
  2. package/Models/DatabaseModels/GlobalConfig.ts +24 -0
  3. package/Models/DatabaseModels/Monitor.ts +3 -2
  4. package/Models/DatabaseModels/MonitorTemplate.ts +2 -1
  5. package/Scripts/generate-service-worker.js +65 -4
  6. package/Server/API/BaseAPI.ts +26 -5
  7. package/Server/API/GlobalConfigAPI.ts +228 -462
  8. package/Server/API/ProjectOIDC.ts +25 -16
  9. package/Server/API/ProjectSSO.ts +24 -16
  10. package/Server/API/StatusPageAPI.ts +100 -42
  11. package/Server/API/TeamMemberAPI.ts +10 -1
  12. package/Server/Enterprise/EnterpriseEdition.ts +649 -0
  13. package/Server/Enterprise/EnterpriseFeature.ts +48 -0
  14. package/Server/Enterprise/EnterpriseLicenseSnapshot.ts +192 -0
  15. package/Server/Enterprise/EnterpriseServerModule.ts +233 -0
  16. package/Server/EnvironmentConfig.ts +147 -2
  17. package/Server/Infrastructure/Postgres/SchemaMigrations/1793900000000-AddEnterpriseEditionFirstSeenAt.ts +25 -0
  18. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +2 -0
  19. package/Server/Middleware/UserAuthorization.ts +38 -16
  20. package/Server/Services/AuditLogService.ts +84 -1079
  21. package/Server/Services/EnterpriseLicenseService.ts +38 -0
  22. package/Server/Services/GlobalConfigService.ts +80 -1
  23. package/Server/Services/MonitorProbeService.ts +116 -20
  24. package/Server/Services/MonitorService.ts +56 -4
  25. package/Server/Services/MonitorStatusTimelineService.ts +284 -0
  26. package/Server/Services/MonitorTemplateService.ts +26 -0
  27. package/Server/Services/ProjectService.ts +284 -0
  28. package/Server/Services/RumSessionPinService.ts +25 -6
  29. package/Server/Services/StatusPagePrivateUserService.ts +7 -3
  30. package/Server/Services/StatusPageService.ts +78 -1
  31. package/Server/Services/TeamMemberService.ts +11 -0
  32. package/Server/Services/TeamService.ts +10 -0
  33. package/Server/Services/UserService.ts +10 -17
  34. package/Server/Types/Database/Permissions/CreatePermission.ts +15 -0
  35. package/Server/Types/Database/Permissions/EditionPermission.ts +208 -18
  36. package/Server/Types/Database/Permissions/TablePermission.ts +10 -3
  37. package/Server/Types/Database/Permissions/UpdatePermission.ts +29 -0
  38. package/Server/Types/Markdown.ts +41 -0
  39. package/Server/Utils/CommunityEditionSsoReport.ts +361 -0
  40. package/Server/Utils/EditionEnforcement.ts +233 -0
  41. package/Server/Utils/FrontendEnvironment.ts +41 -2
  42. package/Server/Utils/InstanceHealth/RedisHealth.ts +12 -277
  43. package/Server/Utils/Monitor/AffectedResourceList.ts +190 -0
  44. package/Server/Utils/Monitor/Criteria/EvaluateOverTime.ts +10 -1
  45. package/Server/Utils/Monitor/MonitorCriteriaEvaluator.ts +543 -333
  46. package/Server/Utils/Monitor/MonitoringIntervalValidator.ts +116 -0
  47. package/Server/Utils/Workspace/Slack/Slack.ts +423 -10
  48. package/Tests/App/Accounts/LoginPasskey.test.tsx +18 -0
  49. package/Tests/App/Accounts/LoginSsoEdition.test.tsx +616 -0
  50. package/Tests/App/AdminDashboard/AdminAuthenticationSsoEdition.test.tsx +217 -0
  51. package/Tests/App/AdminDashboard/AdminEnterprisePluginPage.test.tsx +357 -0
  52. package/Tests/App/AdminDashboard/EnterpriseLicensesShell.test.tsx +214 -0
  53. package/Tests/App/AdminDashboard/GlobalSSOEnterpriseShells.test.tsx +271 -0
  54. package/Tests/App/AdminDashboard/HealthShells.test.tsx +659 -0
  55. package/Tests/App/Dashboard/AuditLogsAndComplianceShells.test.tsx +572 -0
  56. package/Tests/App/Dashboard/EnterpriseFeatureUpgrade.test.tsx +547 -0
  57. package/Tests/App/Dashboard/EnterprisePluginPage.test.tsx +667 -0
  58. package/Tests/App/Dashboard/IdentityEnterpriseShells.test.tsx +319 -0
  59. package/Tests/App/Dashboard/OnboardingSsoEmptyState.test.tsx +185 -0
  60. package/Tests/App/Dashboard/SecurityEventConnectionDiagnostics.test.tsx +45 -9
  61. package/Tests/App/Dashboard/SecurityEventDetailPanel.test.tsx +399 -0
  62. package/Tests/App/Dashboard/SecurityEventListRow.test.tsx +214 -0
  63. package/Tests/App/Dashboard/SecurityEventsEmptyState.test.tsx +1 -83
  64. package/Tests/App/Dashboard/SecurityEventsNavTabs.test.tsx +248 -0
  65. package/Tests/App/Dashboard/SecurityEventsViewer.test.tsx +1203 -0
  66. package/Tests/App/Dashboard/UserEmailCallSites.test.tsx +11 -91
  67. package/Tests/App/StatusPage/StatusPageSsoEmptyState.test.tsx +319 -0
  68. package/Tests/Helpers/RefreshAwareApiScan.ts +757 -0
  69. package/Tests/Helpers/TenantScopedRequestScan.ts +515 -0
  70. package/Tests/Scripts/GenerateServiceWorker.test.ts +931 -0
  71. package/Tests/Server/API/BaseAPICreateItemDoesNotMutateModel.test.ts +130 -0
  72. package/Tests/Server/API/GlobalConfigLicense.test.ts +742 -497
  73. package/Tests/Server/API/OnCallReadinessAPI.test.ts +35 -909
  74. package/Tests/Server/API/SsoProviderListingsEdition.test.ts +432 -0
  75. package/Tests/Server/API/TeamMemberLeaveScimLockEdition.test.ts +252 -0
  76. package/Tests/Server/Enterprise/EnterpriseEdition.test.ts +824 -0
  77. package/Tests/Server/Enterprise/EnterpriseFeatureActive.test.ts +643 -0
  78. package/Tests/Server/Enterprise/EnterpriseLicenseSnapshot.test.ts +294 -0
  79. package/Tests/Server/Enterprise/EnterpriseModelFeatureMap.test.ts +93 -0
  80. package/Tests/Server/Enterprise/EnterpriseOnlyModulesLiveInEe.test.ts +582 -0
  81. package/Tests/Server/Enterprise/EnterpriseServerModule.test.ts +247 -0
  82. package/Tests/Server/Enterprise/FakeEnterpriseModule.ts +502 -0
  83. package/Tests/Server/Enterprise/TestBillingFlag.ts +70 -0
  84. package/Tests/Server/EnvironmentConfigEnterpriseEdition.test.ts +314 -0
  85. package/Tests/Server/Infrastructure/ContainerBootConfiguration.test.ts +289 -0
  86. package/Tests/Server/Infrastructure/E2EClickHouseFixtureAccess.test.ts +5 -1
  87. package/Tests/Server/Middleware/UserAuthorization.test.ts +37 -2
  88. package/Tests/Server/Middleware/UserAuthorizationEditionEnforcement.test.ts +516 -0
  89. package/Tests/Server/Services/AuditLogService.test.ts +460 -990
  90. package/Tests/Server/Services/CreateAndReadResponsesKeepIds.test.ts +263 -0
  91. package/Tests/Server/Services/EnterpriseLicenseServiceKeyGeneration.test.ts +151 -0
  92. package/Tests/Server/Services/GlobalConfigServiceLicenseColumns.test.ts +357 -0
  93. package/Tests/Server/Services/MonitorDestinationInfoIPv6.test.ts +101 -0
  94. package/Tests/Server/Services/MonitorProbeServiceIntervalScheduling.test.ts +333 -0
  95. package/Tests/Server/Services/MonitorStatusTimelineDailyAggregates.test.ts +303 -0
  96. package/Tests/Server/Services/ProjectServiceAuditLogLicense.test.ts +701 -0
  97. package/Tests/Server/Services/ProjectServiceAuditLogSettingsCache.test.ts +31 -35
  98. package/Tests/Server/Services/ScimPushGroupsTeamLocksEdition.test.ts +431 -0
  99. package/Tests/Server/Services/SsoRequirementReadMasking.test.ts +419 -0
  100. package/Tests/Server/Services/SsoRequirementWriteGuard.test.ts +769 -0
  101. package/Tests/Server/Services/StatusPagePrivateUserInvitationPolicy.test.ts +94 -0
  102. package/Tests/Server/Services/UserAuthenticationService.test.ts +35 -0
  103. package/Tests/Server/Services/UserServiceSeatLimit.test.ts +94 -56
  104. package/Tests/Server/Types/Database/Permissions/EditionPermission.test.ts +1823 -0
  105. package/Tests/Server/Types/Markdown.test.ts +181 -0
  106. package/Tests/Server/Utils/CommunityEditionSsoReport.test.ts +565 -0
  107. package/Tests/Server/Utils/EditionEnforcement.test.ts +303 -0
  108. package/Tests/Server/Utils/FrontendEnvironment.test.ts +367 -0
  109. package/Tests/Server/Utils/InstanceHealth/RedisHealth.test.ts +38 -418
  110. package/Tests/Server/Utils/Monitor/AffectedResourceList.test.ts +518 -0
  111. package/Tests/Server/Utils/Monitor/Criteria/EvaluateOverTime.test.ts +24 -4
  112. package/Tests/Server/Utils/Monitor/MonitorCriteriaEvaluator.test.ts +934 -96
  113. package/Tests/Server/Utils/Monitor/MonitoringIntervalValidator.test.ts +188 -0
  114. package/Tests/Server/Utils/Workspace/Slack/SlackMarkdownSectionSplit.test.ts +1209 -0
  115. package/Tests/Types/API/HostnameFromAuthority.test.ts +20 -10
  116. package/Tests/Types/API/HostnameIPv6.test.ts +149 -0
  117. package/Tests/Types/Database/CanonicalModelInstance.test.ts +190 -0
  118. package/Tests/UI/Components/EditionLabelLapseCopy.ts +104 -0
  119. package/Tests/UI/Components/EditionLabelLicenseManagerWiring.test.tsx +254 -0
  120. package/Tests/UI/Components/EditionLabelLicenseRefresh.test.tsx +84 -178
  121. package/Tests/UI/Components/EditionLabelLicenseStatus.test.tsx +1586 -0
  122. package/Tests/UI/Components/EditionLabelLicenseWritesGuard.test.tsx +157 -0
  123. package/Tests/UI/Components/Graphs/DayUptimeGraph.test.tsx +49 -2
  124. package/Tests/UI/Components/MarkdownConverters.test.ts +684 -0
  125. package/Tests/UI/Components/ModelListEmptyState.test.tsx +289 -0
  126. package/Tests/UI/Components/TelemetryViewer/TelemetryViewerEmptyContent.test.tsx +131 -0
  127. package/Tests/UI/EsbuildEnterpriseAlias.test.ts +1127 -0
  128. package/Tests/Utils/HostAddressUtil.test.ts +138 -0
  129. package/Tests/Utils/Monitor/MonitorDestinationUtil.test.ts +313 -0
  130. package/Tests/Utils/Monitor/MonitoringIntervalUtil.test.ts +304 -0
  131. package/Tests/Utils/StatusPage/UptimeDailyAggregateUtil.test.ts +248 -0
  132. package/Types/API/Hostname.ts +63 -16
  133. package/Types/Database/AccessControl/ColumnAccessControl.ts +19 -7
  134. package/Types/Database/AccessControl/ColumnBillingAccessControl.ts +19 -7
  135. package/Types/Database/AccessControl/OwnerOnlyColumn.ts +15 -6
  136. package/Types/Database/CanonicalModelInstance.ts +102 -0
  137. package/Types/Database/TableColumn.ts +20 -6
  138. package/Types/EnterpriseLicense/EnterpriseLicensePeriods.ts +29 -0
  139. package/Types/IP/IPv6.ts +6 -1
  140. package/Types/Monitor/MonitorStep.ts +6 -1
  141. package/Types/Monitor/ProxmoxAlertTemplates.ts +1 -1
  142. package/Types/StatusPage/UptimeDailyAggregate.ts +110 -0
  143. package/UI/Components/EditionLabel/EditionLabel.tsx +796 -1195
  144. package/UI/Components/EditionLabel/LicenseManager.ts +119 -0
  145. package/UI/Components/Graphs/DayUptimeGraph.tsx +123 -15
  146. package/UI/Components/Markdown.tsx/MarkdownConverters.ts +0 -0
  147. package/UI/Components/ModelList/ModelList.tsx +11 -1
  148. package/UI/Components/MonitorGraphs/Uptime.tsx +69 -0
  149. package/UI/Components/TelemetryViewer/TelemetryViewer.tsx +28 -12
  150. package/UI/esbuild-enterprise.js +263 -0
  151. package/Utils/EnterpriseLicense/EnterpriseLicenseUsage.ts +7 -2
  152. package/Utils/HostAddressUtil.ts +94 -0
  153. package/Utils/Monitor/MonitorDestinationUtil.ts +157 -0
  154. package/Utils/Monitor/MonitoringIntervalUtil.ts +436 -0
  155. package/Utils/StatusPage/UptimeDailyAggregateUtil.ts +192 -0
  156. package/build/dist/Models/AnalyticsModels/AuditLog.js +23 -15
  157. package/build/dist/Models/AnalyticsModels/AuditLog.js.map +1 -1
  158. package/build/dist/Models/DatabaseModels/GlobalConfig.js +25 -0
  159. package/build/dist/Models/DatabaseModels/GlobalConfig.js.map +1 -1
  160. package/build/dist/Models/DatabaseModels/Monitor.js +2 -2
  161. package/build/dist/Models/DatabaseModels/Monitor.js.map +1 -1
  162. package/build/dist/Models/DatabaseModels/MonitorTemplate.js +2 -1
  163. package/build/dist/Models/DatabaseModels/MonitorTemplate.js.map +1 -1
  164. package/build/dist/Server/API/BaseAPI.js +26 -5
  165. package/build/dist/Server/API/BaseAPI.js.map +1 -1
  166. package/build/dist/Server/API/GlobalConfigAPI.js +148 -344
  167. package/build/dist/Server/API/GlobalConfigAPI.js.map +1 -1
  168. package/build/dist/Server/API/ProjectOIDC.js +24 -16
  169. package/build/dist/Server/API/ProjectOIDC.js.map +1 -1
  170. package/build/dist/Server/API/ProjectSSO.js +24 -16
  171. package/build/dist/Server/API/ProjectSSO.js.map +1 -1
  172. package/build/dist/Server/API/StatusPageAPI.js +93 -43
  173. package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
  174. package/build/dist/Server/API/TeamMemberAPI.js +8 -1
  175. package/build/dist/Server/API/TeamMemberAPI.js.map +1 -1
  176. package/build/dist/Server/Enterprise/EnterpriseEdition.js +466 -0
  177. package/build/dist/Server/Enterprise/EnterpriseEdition.js.map +1 -0
  178. package/build/dist/Server/Enterprise/EnterpriseFeature.js +39 -0
  179. package/build/dist/Server/Enterprise/EnterpriseFeature.js.map +1 -0
  180. package/build/dist/Server/Enterprise/EnterpriseLicenseSnapshot.js +70 -0
  181. package/build/dist/Server/Enterprise/EnterpriseLicenseSnapshot.js.map +1 -0
  182. package/build/dist/Server/Enterprise/EnterpriseServerModule.js +84 -0
  183. package/build/dist/Server/Enterprise/EnterpriseServerModule.js.map +1 -0
  184. package/build/dist/Server/EnvironmentConfig.js +84 -2
  185. package/build/dist/Server/EnvironmentConfig.js.map +1 -1
  186. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793900000000-AddEnterpriseEditionFirstSeenAt.js +18 -0
  187. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1793900000000-AddEnterpriseEditionFirstSeenAt.js.map +1 -0
  188. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +2 -0
  189. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  190. package/build/dist/Server/Middleware/UserAuthorization.js +30 -11
  191. package/build/dist/Server/Middleware/UserAuthorization.js.map +1 -1
  192. package/build/dist/Server/Services/AuditLogService.js +71 -740
  193. package/build/dist/Server/Services/AuditLogService.js.map +1 -1
  194. package/build/dist/Server/Services/EnterpriseLicenseService.js +34 -0
  195. package/build/dist/Server/Services/EnterpriseLicenseService.js.map +1 -1
  196. package/build/dist/Server/Services/GlobalConfigService.js +63 -0
  197. package/build/dist/Server/Services/GlobalConfigService.js.map +1 -1
  198. package/build/dist/Server/Services/MonitorProbeService.js +90 -17
  199. package/build/dist/Server/Services/MonitorProbeService.js.map +1 -1
  200. package/build/dist/Server/Services/MonitorService.js +45 -4
  201. package/build/dist/Server/Services/MonitorService.js.map +1 -1
  202. package/build/dist/Server/Services/MonitorStatusTimelineService.js +242 -0
  203. package/build/dist/Server/Services/MonitorStatusTimelineService.js.map +1 -1
  204. package/build/dist/Server/Services/MonitorTemplateService.js +16 -0
  205. package/build/dist/Server/Services/MonitorTemplateService.js.map +1 -1
  206. package/build/dist/Server/Services/ProjectService.js +214 -0
  207. package/build/dist/Server/Services/ProjectService.js.map +1 -1
  208. package/build/dist/Server/Services/RumSessionPinService.js +24 -6
  209. package/build/dist/Server/Services/RumSessionPinService.js.map +1 -1
  210. package/build/dist/Server/Services/StatusPagePrivateUserService.js +7 -3
  211. package/build/dist/Server/Services/StatusPagePrivateUserService.js.map +1 -1
  212. package/build/dist/Server/Services/StatusPageService.js +71 -0
  213. package/build/dist/Server/Services/StatusPageService.js.map +1 -1
  214. package/build/dist/Server/Services/TeamMemberService.js +10 -0
  215. package/build/dist/Server/Services/TeamMemberService.js.map +1 -1
  216. package/build/dist/Server/Services/TeamService.js +9 -0
  217. package/build/dist/Server/Services/TeamService.js.map +1 -1
  218. package/build/dist/Server/Services/UserService.js +10 -16
  219. package/build/dist/Server/Services/UserService.js.map +1 -1
  220. package/build/dist/Server/Types/Database/Permissions/CreatePermission.js +10 -0
  221. package/build/dist/Server/Types/Database/Permissions/CreatePermission.js.map +1 -1
  222. package/build/dist/Server/Types/Database/Permissions/EditionPermission.js +154 -14
  223. package/build/dist/Server/Types/Database/Permissions/EditionPermission.js.map +1 -1
  224. package/build/dist/Server/Types/Database/Permissions/TablePermission.js +10 -3
  225. package/build/dist/Server/Types/Database/Permissions/TablePermission.js.map +1 -1
  226. package/build/dist/Server/Types/Database/Permissions/UpdatePermission.js +17 -0
  227. package/build/dist/Server/Types/Database/Permissions/UpdatePermission.js.map +1 -1
  228. package/build/dist/Server/Types/Markdown.js +31 -0
  229. package/build/dist/Server/Types/Markdown.js.map +1 -1
  230. package/build/dist/Server/Utils/CommunityEditionSsoReport.js +223 -0
  231. package/build/dist/Server/Utils/CommunityEditionSsoReport.js.map +1 -0
  232. package/build/dist/Server/Utils/EditionEnforcement.js +187 -0
  233. package/build/dist/Server/Utils/EditionEnforcement.js.map +1 -0
  234. package/build/dist/Server/Utils/FrontendEnvironment.js +31 -2
  235. package/build/dist/Server/Utils/FrontendEnvironment.js.map +1 -1
  236. package/build/dist/Server/Utils/InstanceHealth/RedisHealth.js +6 -193
  237. package/build/dist/Server/Utils/InstanceHealth/RedisHealth.js.map +1 -1
  238. package/build/dist/Server/Utils/Monitor/AffectedResourceList.js +96 -0
  239. package/build/dist/Server/Utils/Monitor/AffectedResourceList.js.map +1 -0
  240. package/build/dist/Server/Utils/Monitor/Criteria/EvaluateOverTime.js +8 -1
  241. package/build/dist/Server/Utils/Monitor/Criteria/EvaluateOverTime.js.map +1 -1
  242. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js +449 -261
  243. package/build/dist/Server/Utils/Monitor/MonitorCriteriaEvaluator.js.map +1 -1
  244. package/build/dist/Server/Utils/Monitor/MonitoringIntervalValidator.js +88 -0
  245. package/build/dist/Server/Utils/Monitor/MonitoringIntervalValidator.js.map +1 -0
  246. package/build/dist/Server/Utils/Workspace/Slack/Slack.js +331 -11
  247. package/build/dist/Server/Utils/Workspace/Slack/Slack.js.map +1 -1
  248. package/build/dist/Types/API/Hostname.js +59 -11
  249. package/build/dist/Types/API/Hostname.js.map +1 -1
  250. package/build/dist/Types/Database/AccessControl/ColumnAccessControl.js +19 -7
  251. package/build/dist/Types/Database/AccessControl/ColumnAccessControl.js.map +1 -1
  252. package/build/dist/Types/Database/AccessControl/ColumnBillingAccessControl.js +19 -7
  253. package/build/dist/Types/Database/AccessControl/ColumnBillingAccessControl.js.map +1 -1
  254. package/build/dist/Types/Database/AccessControl/OwnerOnlyColumn.js +13 -6
  255. package/build/dist/Types/Database/AccessControl/OwnerOnlyColumn.js.map +1 -1
  256. package/build/dist/Types/Database/CanonicalModelInstance.js +88 -0
  257. package/build/dist/Types/Database/CanonicalModelInstance.js.map +1 -0
  258. package/build/dist/Types/Database/TableColumn.js +19 -6
  259. package/build/dist/Types/Database/TableColumn.js.map +1 -1
  260. package/build/dist/Types/EnterpriseLicense/EnterpriseLicensePeriods.js +28 -0
  261. package/build/dist/Types/EnterpriseLicense/EnterpriseLicensePeriods.js.map +1 -0
  262. package/build/dist/Types/IP/IPv6.js +6 -1
  263. package/build/dist/Types/IP/IPv6.js.map +1 -1
  264. package/build/dist/Types/Monitor/MonitorStep.js +5 -0
  265. package/build/dist/Types/Monitor/MonitorStep.js.map +1 -1
  266. package/build/dist/Types/Monitor/ProxmoxAlertTemplates.js +1 -1
  267. package/build/dist/Types/StatusPage/UptimeDailyAggregate.js +32 -0
  268. package/build/dist/Types/StatusPage/UptimeDailyAggregate.js.map +1 -0
  269. package/build/dist/UI/Components/EditionLabel/EditionLabel.js +414 -585
  270. package/build/dist/UI/Components/EditionLabel/EditionLabel.js.map +1 -1
  271. package/build/dist/UI/Components/EditionLabel/LicenseManager.js +2 -0
  272. package/build/dist/UI/Components/EditionLabel/LicenseManager.js.map +1 -0
  273. package/build/dist/UI/Components/Graphs/DayUptimeGraph.js +90 -17
  274. package/build/dist/UI/Components/Graphs/DayUptimeGraph.js.map +1 -1
  275. package/build/dist/UI/Components/Markdown.tsx/MarkdownConverters.js +0 -0
  276. package/build/dist/UI/Components/Markdown.tsx/MarkdownConverters.js.map +1 -1
  277. package/build/dist/UI/Components/ModelList/ModelList.js +4 -1
  278. package/build/dist/UI/Components/ModelList/ModelList.js.map +1 -1
  279. package/build/dist/UI/Components/MonitorGraphs/Uptime.js +42 -1
  280. package/build/dist/UI/Components/MonitorGraphs/Uptime.js.map +1 -1
  281. package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js +2 -2
  282. package/build/dist/UI/Components/TelemetryViewer/TelemetryViewer.js.map +1 -1
  283. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseUsage.js +6 -2
  284. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseUsage.js.map +1 -1
  285. package/build/dist/Utils/HostAddressUtil.js +80 -0
  286. package/build/dist/Utils/HostAddressUtil.js.map +1 -0
  287. package/build/dist/Utils/Monitor/MonitorDestinationUtil.js +127 -0
  288. package/build/dist/Utils/Monitor/MonitorDestinationUtil.js.map +1 -0
  289. package/build/dist/Utils/Monitor/MonitoringIntervalUtil.js +374 -0
  290. package/build/dist/Utils/Monitor/MonitoringIntervalUtil.js.map +1 -0
  291. package/build/dist/Utils/StatusPage/UptimeDailyAggregateUtil.js +148 -0
  292. package/build/dist/Utils/StatusPage/UptimeDailyAggregateUtil.js.map +1 -0
  293. package/jest.config.json +3 -1
  294. package/package.json +1 -1
  295. package/test-setup.sh +103 -34
  296. package/tsconfig.json +13 -0
  297. package/Server/API/EnterpriseLicenseAPI.ts +0 -925
  298. package/Server/API/TeamComplianceAPI.ts +0 -158
  299. package/Server/Middleware/SCIMAuthorization.ts +0 -141
  300. package/Server/Services/TeamComplianceService.ts +0 -733
  301. package/Server/Utils/EnterpriseLicense/EnterpriseLicenseSeatUtil.ts +0 -186
  302. package/Server/Utils/InstanceHealth/PostgresHealth.ts +0 -286
  303. package/Tests/App/AdminDashboard/EnterpriseLicenseInstanceActivity.test.tsx +0 -451
  304. package/Tests/App/Dashboard/AuditLogsTable.test.tsx +0 -598
  305. package/Tests/App/Dashboard/SecurityEventsExplorer.test.tsx +0 -761
  306. package/Tests/App/Dashboard/SecurityEventsSideMenu.test.tsx +0 -247
  307. package/Tests/App/Dashboard/SecurityEventsTableColumns.test.tsx +0 -382
  308. package/Tests/App/Dashboard/SecurityEventsVolumeChart.test.tsx +0 -321
  309. package/Tests/Server/API/EnterpriseLicenseReportUserCount.test.ts +0 -1851
  310. package/Tests/Server/Middleware/SCIMAuthorization.test.ts +0 -525
  311. package/Tests/Server/Services/TeamComplianceServiceBehaviour.test.ts +0 -1845
  312. package/Tests/Server/Utils/EnterpriseLicense/EnterpriseLicenseSeatUtil.test.ts +0 -495
  313. package/Tests/Server/Utils/InstanceHealth/PostgresHealth.test.ts +0 -337
  314. package/Tests/Utils/EnterpriseLicenseSeats.test.ts +0 -576
  315. package/Tests/Utils/EnterpriseLicenseSync.test.ts +0 -568
  316. package/Utils/EnterpriseLicense/EnterpriseLicenseSeats.ts +0 -287
  317. package/Utils/EnterpriseLicense/EnterpriseLicenseSync.ts +0 -244
  318. package/build/dist/Server/API/EnterpriseLicenseAPI.js +0 -646
  319. package/build/dist/Server/API/EnterpriseLicenseAPI.js.map +0 -1
  320. package/build/dist/Server/API/TeamComplianceAPI.js +0 -111
  321. package/build/dist/Server/API/TeamComplianceAPI.js.map +0 -1
  322. package/build/dist/Server/Middleware/SCIMAuthorization.js +0 -124
  323. package/build/dist/Server/Middleware/SCIMAuthorization.js.map +0 -1
  324. package/build/dist/Server/Services/TeamComplianceService.js +0 -537
  325. package/build/dist/Server/Services/TeamComplianceService.js.map +0 -1
  326. package/build/dist/Server/Utils/EnterpriseLicense/EnterpriseLicenseSeatUtil.js +0 -145
  327. package/build/dist/Server/Utils/EnterpriseLicense/EnterpriseLicenseSeatUtil.js.map +0 -1
  328. package/build/dist/Server/Utils/InstanceHealth/PostgresHealth.js +0 -194
  329. package/build/dist/Server/Utils/InstanceHealth/PostgresHealth.js.map +0 -1
  330. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSeats.js +0 -168
  331. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSeats.js.map +0 -1
  332. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSync.js +0 -174
  333. package/build/dist/Utils/EnterpriseLicense/EnterpriseLicenseSync.js.map +0 -1
@@ -0,0 +1,502 @@
1
+ import { jest } from "@jest/globals";
2
+ import EnterpriseEdition from "../../../Server/Enterprise/EnterpriseEdition";
3
+ import EnterpriseFeature from "../../../Server/Enterprise/EnterpriseFeature";
4
+ import {
5
+ EnterpriseLicenseSnapshot,
6
+ EnterpriseLicenseStatus,
7
+ SeatUsage,
8
+ } from "../../../Server/Enterprise/EnterpriseLicenseSnapshot";
9
+ import EnterpriseServerModule, {
10
+ AuditLogRecorder,
11
+ ENTERPRISE_SERVER_MODULE_NAME,
12
+ EnterpriseLicensingProvider,
13
+ } from "../../../Server/Enterprise/EnterpriseServerModule";
14
+ import type { ExpressRouter } from "../../../Server/Utils/Express";
15
+ import { setTestBillingEnabled } from "./TestBillingFlag";
16
+
17
+ /*
18
+ * Test kit for anything that behaves differently per edition.
19
+ *
20
+ * Every suite that touches gated code pins BOTH halves of the state:
21
+ * - billing, with TestBillingFlag (CI's config.env sets BILLING_ENABLED=true)
22
+ * - the edition, with installFakeEnterpriseModule(...) for "EE loaded" or
23
+ * uninstallEnterpriseModule() for "Community Edition"
24
+ */
25
+
26
+ const DAY_IN_MS: number = 24 * 60 * 60 * 1000;
27
+
28
+ // A current, fully entitled, verified license. Override what the test is about.
29
+ export const createLicenseSnapshot: (
30
+ overrides?: Partial<EnterpriseLicenseSnapshot>,
31
+ ) => EnterpriseLicenseSnapshot = (
32
+ overrides?: Partial<EnterpriseLicenseSnapshot>,
33
+ ): EnterpriseLicenseSnapshot => {
34
+ return {
35
+ status: "valid",
36
+ verification: "verified",
37
+ companyName: "Acme Inc",
38
+ expiresAt: new Date(Date.now() + 365 * DAY_IN_MS),
39
+ userLimit: null,
40
+ isEvaluation: false,
41
+ features: "all",
42
+ ...(overrides || {}),
43
+ };
44
+ };
45
+
46
+ /*
47
+ * A snapshot in the given status, with the fields that status normally
48
+ * carries. "missing" is an install whose trial ended a day ago (graceEndsAt
49
+ * in the past): a known lapse. Pass graceEndsAt: undefined for "the trial
50
+ * start is not known", which isFeatureActive treats as an unknown state.
51
+ */
52
+ export const createLicenseSnapshotWithStatus: (
53
+ status: EnterpriseLicenseStatus,
54
+ overrides?: Partial<EnterpriseLicenseSnapshot>,
55
+ ) => EnterpriseLicenseSnapshot = (
56
+ status: EnterpriseLicenseStatus,
57
+ overrides?: Partial<EnterpriseLicenseSnapshot>,
58
+ ): EnterpriseLicenseSnapshot => {
59
+ const now: number = Date.now();
60
+
61
+ switch (status) {
62
+ case "missing":
63
+ return createLicenseSnapshot({
64
+ status,
65
+ verification: "none",
66
+ companyName: undefined,
67
+ expiresAt: undefined,
68
+ graceEndsAt: new Date(now - DAY_IN_MS),
69
+ features: [],
70
+ ...(overrides || {}),
71
+ });
72
+ case "grace":
73
+ return createLicenseSnapshot({
74
+ status,
75
+ graceReason: "expired",
76
+ // Two days into the 30-day grace period.
77
+ expiresAt: new Date(now - 2 * DAY_IN_MS),
78
+ graceEndsAt: new Date(now + 28 * DAY_IN_MS),
79
+ ...(overrides || {}),
80
+ });
81
+ case "expired":
82
+ return createLicenseSnapshot({
83
+ status,
84
+ // Past the 30-day grace period.
85
+ expiresAt: new Date(now - 45 * DAY_IN_MS),
86
+ ...(overrides || {}),
87
+ });
88
+ case "invalid":
89
+ return createLicenseSnapshot({
90
+ status,
91
+ message: "The license token signature does not verify.",
92
+ ...(overrides || {}),
93
+ });
94
+ case "valid":
95
+ default:
96
+ return createLicenseSnapshot({ status, ...(overrides || {}) });
97
+ }
98
+ };
99
+
100
+ /*
101
+ * Each method is both the recorder method and a jest spy, so a test can assert
102
+ * on calls (toHaveBeenCalledWith) without casting.
103
+ */
104
+ export type MockedAuditLogRecorder = {
105
+ [K in keyof AuditLogRecorder]: AuditLogRecorder[K] & jest.Mock;
106
+ };
107
+
108
+ // An audit-log recorder whose four methods are jest spies that do nothing.
109
+ export const createAuditLogRecorderSpy: () => MockedAuditLogRecorder =
110
+ (): MockedAuditLogRecorder => {
111
+ return {
112
+ recordCreate: jest.fn(async (): Promise<void> => {
113
+ return undefined;
114
+ }) as unknown as MockedAuditLogRecorder["recordCreate"],
115
+ recordUpdate: jest.fn(async (): Promise<void> => {
116
+ return undefined;
117
+ }) as unknown as MockedAuditLogRecorder["recordUpdate"],
118
+ recordDelete: jest.fn(async (): Promise<void> => {
119
+ return undefined;
120
+ }) as unknown as MockedAuditLogRecorder["recordDelete"],
121
+ invalidateProjectSettings: jest.fn((): void => {
122
+ return undefined;
123
+ }) as unknown as MockedAuditLogRecorder["invalidateProjectSettings"],
124
+ };
125
+ };
126
+
127
+ export interface FakeEnterpriseModuleOptions {
128
+ /*
129
+ * What getCachedSnapshot() and getSnapshot() return. Defaults to a valid,
130
+ * fully entitled license. Null models "the first load has not finished".
131
+ */
132
+ snapshot?: EnterpriseLicenseSnapshot | null | undefined;
133
+ /*
134
+ * What getSnapshot() returns when it should differ from the cached one (for
135
+ * example a fresher read). Defaults to `snapshot`.
136
+ */
137
+ asyncSnapshot?: EnterpriseLicenseSnapshot | null | undefined;
138
+ seatUsage?: SeatUsage | null | undefined;
139
+ // When set, assertSeatAvailableForNewUser rejects with it.
140
+ seatError?: Error | undefined;
141
+ identityRouters?: Array<ExpressRouter> | undefined;
142
+ apiRouters?: Array<ExpressRouter> | undefined;
143
+ adminHealthRouter?: ExpressRouter | null | undefined;
144
+ // Defaults to a fresh spy recorder; pass null for "ee without a recorder".
145
+ auditLogRecorder?: AuditLogRecorder | null | undefined;
146
+ version?: string | undefined;
147
+ }
148
+
149
+ class FakeLicensingProvider implements EnterpriseLicensingProvider {
150
+ public cachedSnapshot: EnterpriseLicenseSnapshot | null;
151
+ public asyncSnapshot: EnterpriseLicenseSnapshot | null;
152
+ public seatUsage: SeatUsage | null;
153
+ public seatError: Error | undefined;
154
+ public getCachedSnapshotError: Error | undefined = undefined;
155
+ public getSnapshotError: Error | undefined = undefined;
156
+ public refreshCount: number = 0;
157
+ public invalidateCount: number = 0;
158
+ public seatChecks: number = 0;
159
+
160
+ public constructor(options: FakeEnterpriseModuleOptions) {
161
+ this.cachedSnapshot =
162
+ options.snapshot === undefined
163
+ ? createLicenseSnapshot()
164
+ : options.snapshot;
165
+ this.asyncSnapshot =
166
+ options.asyncSnapshot === undefined
167
+ ? this.cachedSnapshot
168
+ : options.asyncSnapshot;
169
+ this.seatUsage = options.seatUsage === undefined ? null : options.seatUsage;
170
+ this.seatError = options.seatError;
171
+ }
172
+
173
+ public async getSnapshot(): Promise<EnterpriseLicenseSnapshot> {
174
+ if (this.getSnapshotError) {
175
+ throw this.getSnapshotError;
176
+ }
177
+
178
+ if (!this.asyncSnapshot) {
179
+ throw new Error("FakeLicensingProvider: no snapshot configured");
180
+ }
181
+
182
+ return this.asyncSnapshot;
183
+ }
184
+
185
+ public getCachedSnapshot(): EnterpriseLicenseSnapshot | null {
186
+ if (this.getCachedSnapshotError) {
187
+ throw this.getCachedSnapshotError;
188
+ }
189
+
190
+ return this.cachedSnapshot;
191
+ }
192
+
193
+ public async refresh(): Promise<void> {
194
+ this.refreshCount++;
195
+ }
196
+
197
+ public invalidate(): void {
198
+ this.invalidateCount++;
199
+ }
200
+
201
+ public async getSeatUsage(): Promise<SeatUsage | null> {
202
+ return this.seatUsage;
203
+ }
204
+
205
+ public async assertSeatAvailableForNewUser(): Promise<void> {
206
+ this.seatChecks++;
207
+
208
+ if (this.seatError) {
209
+ throw this.seatError;
210
+ }
211
+ }
212
+ }
213
+
214
+ export default class FakeEnterpriseModule implements EnterpriseServerModule {
215
+ public readonly name: typeof ENTERPRISE_SERVER_MODULE_NAME =
216
+ ENTERPRISE_SERVER_MODULE_NAME;
217
+ public readonly version: string;
218
+ public readonly licensing: FakeLicensingProvider;
219
+ public identityRouters: Array<ExpressRouter>;
220
+ public apiRouters: Array<ExpressRouter>;
221
+ public adminHealthRouter: ExpressRouter | null;
222
+ public auditLogRecorder: AuditLogRecorder | null;
223
+ public initCount: number = 0;
224
+ public registerWorkerJobsCount: number = 0;
225
+
226
+ public constructor(options: FakeEnterpriseModuleOptions = {}) {
227
+ this.version = options.version || "0.0.0-test";
228
+ this.licensing = new FakeLicensingProvider(options);
229
+ this.identityRouters = options.identityRouters || [];
230
+ this.apiRouters = options.apiRouters || [];
231
+ this.adminHealthRouter = options.adminHealthRouter || null;
232
+ this.auditLogRecorder =
233
+ options.auditLogRecorder === undefined
234
+ ? createAuditLogRecorderSpy()
235
+ : options.auditLogRecorder;
236
+ }
237
+
238
+ public async init(): Promise<void> {
239
+ this.initCount++;
240
+ }
241
+
242
+ public getIdentityRouters(): Array<ExpressRouter> {
243
+ return this.identityRouters;
244
+ }
245
+
246
+ public getApiRouters(): Array<ExpressRouter> {
247
+ return this.apiRouters;
248
+ }
249
+
250
+ public getAdminHealthRouter(): ExpressRouter | null {
251
+ return this.adminHealthRouter;
252
+ }
253
+
254
+ public async registerWorkerJobs(): Promise<void> {
255
+ this.registerWorkerJobsCount++;
256
+ }
257
+
258
+ public getAuditLogRecorder(): AuditLogRecorder | null {
259
+ return this.auditLogRecorder;
260
+ }
261
+
262
+ // Replaces both the cached and the async snapshot.
263
+ public setSnapshot(snapshot: EnterpriseLicenseSnapshot | null): void {
264
+ this.licensing.cachedSnapshot = snapshot;
265
+ this.licensing.asyncSnapshot = snapshot;
266
+ }
267
+ }
268
+
269
+ /*
270
+ * "EE is loaded" with the given license state: forgets any earlier module and
271
+ * registers a fresh fake. Returns it so the test can inspect or change it.
272
+ */
273
+ export const installFakeEnterpriseModule: (
274
+ options?: FakeEnterpriseModuleOptions,
275
+ ) => FakeEnterpriseModule = (
276
+ options?: FakeEnterpriseModuleOptions,
277
+ ): FakeEnterpriseModule => {
278
+ const fake: FakeEnterpriseModule = new FakeEnterpriseModule(options || {});
279
+ EnterpriseEdition.resetForTests();
280
+ EnterpriseEdition.register(fake);
281
+ return fake;
282
+ };
283
+
284
+ // A fake whose license entitles exactly `features` (valid, verified).
285
+ export const installFakeEnterpriseModuleWithFeatures: (
286
+ features: Array<EnterpriseFeature>,
287
+ ) => FakeEnterpriseModule = (
288
+ features: Array<EnterpriseFeature>,
289
+ ): FakeEnterpriseModule => {
290
+ return installFakeEnterpriseModule({
291
+ snapshot: createLicenseSnapshot({ features }),
292
+ });
293
+ };
294
+
295
+ // "Community Edition": no enterprise module in the process.
296
+ export const uninstallEnterpriseModule: () => void = (): void => {
297
+ EnterpriseEdition.resetForTests();
298
+ };
299
+
300
+ /*
301
+ * ---------------------------------------------------------------------------
302
+ * License states for the RUNTIME features (SSO, SCIM, audit logging), which
303
+ * follow EnterpriseEdition.isFeatureActive: with billing off they run while
304
+ * the license covers them and stop when it lapses; an UNKNOWN license state
305
+ * (not read yet, or unreadable) counts as active.
306
+ * ---------------------------------------------------------------------------
307
+ */
308
+ export interface LicenseStateCase {
309
+ label: string;
310
+ // Registers a fresh fake enterprise module in this license state.
311
+ install: () => FakeEnterpriseModule;
312
+ // Whether SSO, SCIM and audit logging run in this state with billing off.
313
+ isActiveWithoutBilling: boolean;
314
+ /*
315
+ * The unknown states: active for runtime checks, but unavailable for
316
+ * configuration checks (isFeatureAvailableSync fails closed).
317
+ */
318
+ isUnknown: boolean;
319
+ }
320
+
321
+ // A license that entitles everything except the three runtime features.
322
+ export const FEATURES_WITHOUT_RUNTIME_FEATURES: Array<EnterpriseFeature> = [
323
+ EnterpriseFeature.TeamCompliance,
324
+ EnterpriseFeature.InstanceHealth,
325
+ ];
326
+
327
+ export const LICENSE_STATE_CASES: ReadonlyArray<LicenseStateCase> = [
328
+ {
329
+ label: "valid license",
330
+ install: (): FakeEnterpriseModule => {
331
+ return installFakeEnterpriseModule({
332
+ snapshot: createLicenseSnapshotWithStatus("valid"),
333
+ });
334
+ },
335
+ isActiveWithoutBilling: true,
336
+ isUnknown: false,
337
+ },
338
+ {
339
+ label: "license expired less than 30 days ago (grace)",
340
+ install: (): FakeEnterpriseModule => {
341
+ return installFakeEnterpriseModule({
342
+ snapshot: createLicenseSnapshotWithStatus("grace"),
343
+ });
344
+ },
345
+ isActiveWithoutBilling: true,
346
+ isUnknown: false,
347
+ },
348
+ {
349
+ label: "no license, inside the 14-day trial",
350
+ install: (): FakeEnterpriseModule => {
351
+ return installFakeEnterpriseModule({
352
+ snapshot: createLicenseSnapshotWithStatus("grace", {
353
+ graceReason: "unlicensed",
354
+ verification: "none",
355
+ companyName: undefined,
356
+ expiresAt: undefined,
357
+ graceEndsAt: new Date(Date.now() + 5 * DAY_IN_MS),
358
+ features: "all",
359
+ }),
360
+ });
361
+ },
362
+ isActiveWithoutBilling: true,
363
+ isUnknown: false,
364
+ },
365
+ {
366
+ label: "unverified legacy license, accepted",
367
+ install: (): FakeEnterpriseModule => {
368
+ return installFakeEnterpriseModule({
369
+ snapshot: createLicenseSnapshotWithStatus("valid", {
370
+ verification: "unverified",
371
+ }),
372
+ });
373
+ },
374
+ isActiveWithoutBilling: true,
375
+ isUnknown: false,
376
+ },
377
+ {
378
+ label: "license expired more than 30 days ago",
379
+ install: (): FakeEnterpriseModule => {
380
+ return installFakeEnterpriseModule({
381
+ snapshot: createLicenseSnapshotWithStatus("expired"),
382
+ });
383
+ },
384
+ isActiveWithoutBilling: false,
385
+ isUnknown: false,
386
+ },
387
+ {
388
+ label: "no license after the trial",
389
+ install: (): FakeEnterpriseModule => {
390
+ return installFakeEnterpriseModule({
391
+ snapshot: createLicenseSnapshotWithStatus("missing", {
392
+ graceEndsAt: new Date(Date.now() - DAY_IN_MS),
393
+ }),
394
+ });
395
+ },
396
+ isActiveWithoutBilling: false,
397
+ isUnknown: false,
398
+ },
399
+ {
400
+ label: "invalid license",
401
+ install: (): FakeEnterpriseModule => {
402
+ return installFakeEnterpriseModule({
403
+ snapshot: createLicenseSnapshotWithStatus("invalid"),
404
+ });
405
+ },
406
+ isActiveWithoutBilling: false,
407
+ isUnknown: false,
408
+ },
409
+ {
410
+ label: "valid license without SSO, SCIM or audit logs",
411
+ install: (): FakeEnterpriseModule => {
412
+ return installFakeEnterpriseModule({
413
+ snapshot: createLicenseSnapshotWithStatus("valid", {
414
+ features: [...FEATURES_WITHOUT_RUNTIME_FEATURES],
415
+ }),
416
+ });
417
+ },
418
+ isActiveWithoutBilling: false,
419
+ isUnknown: false,
420
+ },
421
+ {
422
+ label: "license not read yet (unknown)",
423
+ install: (): FakeEnterpriseModule => {
424
+ return installFakeEnterpriseModule({ snapshot: null });
425
+ },
426
+ isActiveWithoutBilling: true,
427
+ isUnknown: true,
428
+ },
429
+ {
430
+ label: "no license, trial start not recorded yet (unknown)",
431
+ install: (): FakeEnterpriseModule => {
432
+ return installFakeEnterpriseModule({
433
+ snapshot: createLicenseSnapshotWithStatus("missing", {
434
+ graceEndsAt: undefined,
435
+ }),
436
+ });
437
+ },
438
+ isActiveWithoutBilling: true,
439
+ isUnknown: true,
440
+ },
441
+ {
442
+ label: "license snapshot unreadable (unknown)",
443
+ install: (): FakeEnterpriseModule => {
444
+ const fake: FakeEnterpriseModule = installFakeEnterpriseModule();
445
+ fake.licensing.getCachedSnapshotError = new Error(
446
+ "the cached snapshot cannot be read",
447
+ );
448
+ return fake;
449
+ },
450
+ isActiveWithoutBilling: true,
451
+ isUnknown: true,
452
+ },
453
+ ];
454
+
455
+ /*
456
+ * One deployment state: billing, edition and license together, with whether
457
+ * the runtime features run in it. apply() pins BOTH billing and the edition,
458
+ * so a suite that loops over these needs nothing else (it must still mock
459
+ * EnvironmentConfig with TestBillingFlag.withLiveBillingFlag).
460
+ */
461
+ export interface EditionStateCase {
462
+ label: string;
463
+ billing: boolean;
464
+ isLoaded: boolean;
465
+ // Whether SSO, SCIM and audit logging run in this state.
466
+ isActive: boolean;
467
+ apply: () => FakeEnterpriseModule | null;
468
+ }
469
+
470
+ export const createEditionStateCases: () => Array<EditionStateCase> =
471
+ (): Array<EditionStateCase> => {
472
+ const cases: Array<EditionStateCase> = [];
473
+
474
+ for (const billing of [false, true]) {
475
+ cases.push({
476
+ label: `billing=${billing}, Community Edition`,
477
+ billing,
478
+ isLoaded: false,
479
+ isActive: false,
480
+ apply: (): null => {
481
+ setTestBillingEnabled(billing);
482
+ uninstallEnterpriseModule();
483
+ return null;
484
+ },
485
+ });
486
+
487
+ for (const licenseState of LICENSE_STATE_CASES) {
488
+ cases.push({
489
+ label: `billing=${billing}, Enterprise Edition, ${licenseState.label}`,
490
+ billing,
491
+ isLoaded: true,
492
+ isActive: billing || licenseState.isActiveWithoutBilling,
493
+ apply: (): FakeEnterpriseModule => {
494
+ setTestBillingEnabled(billing);
495
+ return licenseState.install();
496
+ },
497
+ });
498
+ }
499
+ }
500
+
501
+ return cases;
502
+ };
@@ -0,0 +1,70 @@
1
+ /*
2
+ * A live, per-test billing switch for suites that touch edition gating.
3
+ *
4
+ * CI's config.env sets BILLING_ENABLED=true, so a suite that does not pin
5
+ * billing silently tests the SaaS path in CI and the self-hosted path locally.
6
+ * Every suite that exercises EnterpriseEdition (directly or through a gate)
7
+ * must pin BOTH billing and the registered module.
8
+ *
9
+ * This file deliberately imports nothing: it is loaded from inside a hoisted
10
+ * jest.mock factory, before any of the test file's own imports exist.
11
+ *
12
+ * jest.mock("<path>/Server/EnvironmentConfig", () => {
13
+ * const flag: typeof import("<path>/Tests/Server/Enterprise/TestBillingFlag") =
14
+ * jest.requireActual("<path>/Tests/Server/Enterprise/TestBillingFlag") as
15
+ * typeof import("<path>/Tests/Server/Enterprise/TestBillingFlag");
16
+ * return flag.withLiveBillingFlag(
17
+ * jest.requireActual("<path>/Server/EnvironmentConfig") as
18
+ * Record<string, unknown>,
19
+ * );
20
+ * });
21
+ *
22
+ * setTestBillingEnabled(false); // in beforeEach, or per test
23
+ *
24
+ * The flag lives on globalThis and the getter reads nothing else, so a module
25
+ * that reads IsBillingEnabled while the mock is being built (some services do,
26
+ * at module scope) sees `false` instead of hitting a temporal-dead-zone error.
27
+ */
28
+ export const TEST_BILLING_FLAG_KEY: string =
29
+ "__oneUptimeEnterpriseTestIsBillingEnabled";
30
+
31
+ type GlobalFlags = Record<string, unknown>;
32
+
33
+ export const setTestBillingEnabled: (value: boolean) => void = (
34
+ value: boolean,
35
+ ): void => {
36
+ (globalThis as unknown as GlobalFlags)[TEST_BILLING_FLAG_KEY] = value;
37
+ };
38
+
39
+ export const isTestBillingEnabled: () => boolean = (): boolean => {
40
+ return (globalThis as unknown as GlobalFlags)[TEST_BILLING_FLAG_KEY] === true;
41
+ };
42
+
43
+ /*
44
+ * A copy of the real EnvironmentConfig exports whose IsBillingEnabled is a live
45
+ * getter over the flag above. A getter rather than a value, because object
46
+ * spread would freeze it at import time.
47
+ */
48
+ export const withLiveBillingFlag: (
49
+ actualEnvironmentConfig: Record<string, unknown>,
50
+ ) => Record<string, unknown> = (
51
+ actualEnvironmentConfig: Record<string, unknown>,
52
+ ): Record<string, unknown> => {
53
+ const mocked: Record<string, unknown> = {
54
+ ...actualEnvironmentConfig,
55
+ __esModule: true,
56
+ };
57
+
58
+ Object.defineProperty(mocked, "IsBillingEnabled", {
59
+ enumerable: true,
60
+ get: (): boolean => {
61
+ return (
62
+ (globalThis as unknown as GlobalFlags)[
63
+ "__oneUptimeEnterpriseTestIsBillingEnabled"
64
+ ] === true
65
+ );
66
+ },
67
+ });
68
+
69
+ return mocked;
70
+ };