@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,643 @@
1
+ import {
2
+ afterAll,
3
+ afterEach,
4
+ beforeEach,
5
+ describe,
6
+ expect,
7
+ jest,
8
+ test,
9
+ } from "@jest/globals";
10
+ import EnterpriseEdition, {
11
+ EnterpriseFeatureStateChange,
12
+ RUNTIME_ENTERPRISE_FEATURES,
13
+ } from "../../../Server/Enterprise/EnterpriseEdition";
14
+ import EnterpriseFeature, {
15
+ ALL_ENTERPRISE_FEATURES,
16
+ } from "../../../Server/Enterprise/EnterpriseFeature";
17
+ import { EnterpriseLicenseSnapshot } from "../../../Server/Enterprise/EnterpriseLicenseSnapshot";
18
+ import logger from "../../../Server/Utils/Logger";
19
+ import FakeEnterpriseModule, {
20
+ createLicenseSnapshot,
21
+ createLicenseSnapshotWithStatus,
22
+ createEditionStateCases,
23
+ EditionStateCase,
24
+ installFakeEnterpriseModule,
25
+ LICENSE_STATE_CASES,
26
+ LicenseStateCase,
27
+ uninstallEnterpriseModule,
28
+ } from "./FakeEnterpriseModule";
29
+ import { setTestBillingEnabled } from "./TestBillingFlag";
30
+ import { getJestSpyOn } from "../../Spy";
31
+
32
+ type SpyInstance = ReturnType<typeof getJestSpyOn>;
33
+
34
+ /*
35
+ * EnterpriseEdition.isFeatureActive: whether a feature's RUNTIME behaviour
36
+ * (SSO sign-in and "Require SSO" enforcement, SCIM provisioning and its team
37
+ * locks, audit-log recording) runs right now.
38
+ *
39
+ * - Community Edition: never;
40
+ * - billing on (OneUptime Cloud): always, plan tiers gate instead;
41
+ * - self-hosted: while the license covers the feature (valid, grace, trial,
42
+ * accepted unverified legacy), and NOT once it lapsed (expired past grace,
43
+ * missing past the trial, invalid, feature not in the license);
44
+ * - unknown license state (not read yet, unreadable, or no license with no
45
+ * recorded trial start): active, with one warning per process - an
46
+ * unknown state must never lock anyone out or relax SSO.
47
+ *
48
+ * A change of answer is logged once per change and reported to listeners.
49
+ * Billing is pinned through the mocked EnvironmentConfig (CI's config.env sets
50
+ * BILLING_ENABLED=true). This suite must pass with ee/ deleted.
51
+ */
52
+ jest.mock("../../../Server/EnvironmentConfig", () => {
53
+ const billingFlag: typeof import("./TestBillingFlag") = jest.requireActual(
54
+ "./TestBillingFlag",
55
+ ) as typeof import("./TestBillingFlag");
56
+
57
+ return billingFlag.withLiveBillingFlag(
58
+ jest.requireActual("../../../Server/EnvironmentConfig") as Record<
59
+ string,
60
+ unknown
61
+ >,
62
+ );
63
+ });
64
+
65
+ let warn: SpyInstance;
66
+ let info: SpyInstance;
67
+ let error: SpyInstance;
68
+
69
+ const warnings: () => Array<string> = (): Array<string> => {
70
+ return warn.mock.calls
71
+ .map((call: Array<unknown>): unknown => {
72
+ return call[0];
73
+ })
74
+ .filter((value: unknown): value is string => {
75
+ return typeof value === "string";
76
+ });
77
+ };
78
+
79
+ const infos: () => Array<string> = (): Array<string> => {
80
+ return info.mock.calls
81
+ .map((call: Array<unknown>): unknown => {
82
+ return call[0];
83
+ })
84
+ .filter((value: unknown): value is string => {
85
+ return typeof value === "string";
86
+ });
87
+ };
88
+
89
+ const lapseWarnings: () => Array<string> = (): Array<string> => {
90
+ return warnings().filter((message: string): boolean => {
91
+ return message.startsWith("The OneUptime Enterprise license");
92
+ });
93
+ };
94
+
95
+ beforeEach(() => {
96
+ uninstallEnterpriseModule();
97
+ setTestBillingEnabled(false);
98
+ warn = getJestSpyOn(logger, "warn").mockImplementation((): void => {
99
+ return undefined;
100
+ });
101
+ info = getJestSpyOn(logger, "info").mockImplementation((): void => {
102
+ return undefined;
103
+ });
104
+ error = getJestSpyOn(logger, "error").mockImplementation((): void => {
105
+ return undefined;
106
+ });
107
+ });
108
+
109
+ afterEach(() => {
110
+ uninstallEnterpriseModule();
111
+ setTestBillingEnabled(false);
112
+ jest.restoreAllMocks();
113
+ });
114
+
115
+ afterAll(() => {
116
+ uninstallEnterpriseModule();
117
+ });
118
+
119
+ describe("isFeatureActive matrix", () => {
120
+ const cases: Array<EditionStateCase> = createEditionStateCases();
121
+
122
+ test("the matrix covers both editions, both billing values and every license state", () => {
123
+ expect(cases).toHaveLength(2 * (1 + LICENSE_STATE_CASES.length));
124
+ expect(
125
+ cases.filter((editionCase: EditionStateCase): boolean => {
126
+ return editionCase.isActive;
127
+ }).length,
128
+ ).toBeGreaterThan(0);
129
+ expect(
130
+ cases.filter((editionCase: EditionStateCase): boolean => {
131
+ return !editionCase.isActive && editionCase.isLoaded;
132
+ }).length,
133
+ ).toBeGreaterThan(0);
134
+ });
135
+
136
+ test.each(
137
+ cases.map((editionCase: EditionStateCase): [string, EditionStateCase] => {
138
+ return [editionCase.label, editionCase];
139
+ }),
140
+ )("%s", (_label: string, editionCase: EditionStateCase) => {
141
+ editionCase.apply();
142
+
143
+ for (const feature of RUNTIME_ENTERPRISE_FEATURES) {
144
+ expect(`${feature}: ${EnterpriseEdition.isFeatureActive(feature)}`).toBe(
145
+ `${feature}: ${editionCase.isActive}`,
146
+ );
147
+ }
148
+
149
+ expect(EnterpriseEdition.isLoaded()).toBe(editionCase.isLoaded);
150
+ });
151
+
152
+ test.each(
153
+ LICENSE_STATE_CASES.map(
154
+ (licenseState: LicenseStateCase): [string, LicenseStateCase] => {
155
+ return [licenseState.label, licenseState];
156
+ },
157
+ ),
158
+ )(
159
+ "billing off, %s: differs from isFeatureAvailableSync only in the unknown states",
160
+ (_label: string, licenseState: LicenseStateCase) => {
161
+ licenseState.install();
162
+
163
+ for (const feature of ALL_ENTERPRISE_FEATURES) {
164
+ const isActive: boolean = EnterpriseEdition.isFeatureActive(feature);
165
+ const isAvailable: boolean =
166
+ EnterpriseEdition.isFeatureAvailableSync(feature);
167
+
168
+ if (licenseState.isUnknown) {
169
+ expect({ feature, isActive, isAvailable }).toEqual({
170
+ feature,
171
+ isActive: true,
172
+ isAvailable: false,
173
+ });
174
+ } else {
175
+ expect({ feature, isActive }).toEqual({
176
+ feature,
177
+ isActive: isAvailable,
178
+ });
179
+ }
180
+ }
181
+ },
182
+ );
183
+
184
+ test("the Community Edition never reads anything and is never active", () => {
185
+ for (const billing of [false, true]) {
186
+ setTestBillingEnabled(billing);
187
+
188
+ for (const feature of ALL_ENTERPRISE_FEATURES) {
189
+ expect(EnterpriseEdition.isFeatureActive(feature)).toBe(false);
190
+ }
191
+ }
192
+
193
+ expect(warn).not.toHaveBeenCalled();
194
+ });
195
+
196
+ test("billing on never reads the license (the Cloud gates by plan)", () => {
197
+ setTestBillingEnabled(true);
198
+ const fake: FakeEnterpriseModule = installFakeEnterpriseModule({
199
+ snapshot: createLicenseSnapshotWithStatus("expired"),
200
+ });
201
+ fake.licensing.getCachedSnapshotError = new Error("must not be read");
202
+
203
+ for (const feature of ALL_ENTERPRISE_FEATURES) {
204
+ expect(EnterpriseEdition.isFeatureActive(feature)).toBe(true);
205
+ }
206
+
207
+ expect(warn).not.toHaveBeenCalled();
208
+ });
209
+
210
+ test("a license that leaves out one feature stops only that feature", () => {
211
+ installFakeEnterpriseModule({
212
+ snapshot: createLicenseSnapshot({
213
+ features: ALL_ENTERPRISE_FEATURES.filter(
214
+ (feature: EnterpriseFeature): boolean => {
215
+ return feature !== EnterpriseFeature.SCIM;
216
+ },
217
+ ),
218
+ }),
219
+ });
220
+
221
+ expect(EnterpriseEdition.isFeatureActive(EnterpriseFeature.SSO)).toBe(true);
222
+ expect(EnterpriseEdition.isFeatureActive(EnterpriseFeature.SCIM)).toBe(
223
+ false,
224
+ );
225
+ expect(EnterpriseEdition.isFeatureActive(EnterpriseFeature.AuditLogs)).toBe(
226
+ true,
227
+ );
228
+ });
229
+
230
+ test("the answer follows the license at call time (renewal and lapse without a restart)", () => {
231
+ const fake: FakeEnterpriseModule = installFakeEnterpriseModule({
232
+ snapshot: createLicenseSnapshotWithStatus("expired"),
233
+ });
234
+
235
+ expect(EnterpriseEdition.isFeatureActive(EnterpriseFeature.SSO)).toBe(
236
+ false,
237
+ );
238
+
239
+ fake.setSnapshot(createLicenseSnapshotWithStatus("valid"));
240
+ expect(EnterpriseEdition.isFeatureActive(EnterpriseFeature.SSO)).toBe(true);
241
+
242
+ fake.setSnapshot(createLicenseSnapshotWithStatus("invalid"));
243
+ expect(EnterpriseEdition.isFeatureActive(EnterpriseFeature.SSO)).toBe(
244
+ false,
245
+ );
246
+ });
247
+ });
248
+
249
+ describe("an unknown license state counts as active, and is warned about once", () => {
250
+ test("not read yet: active, one warning however many calls", () => {
251
+ installFakeEnterpriseModule({ snapshot: null });
252
+
253
+ for (let call: number = 0; call < 25; call++) {
254
+ for (const feature of RUNTIME_ENTERPRISE_FEATURES) {
255
+ expect(EnterpriseEdition.isFeatureActive(feature)).toBe(true);
256
+ }
257
+ }
258
+
259
+ expect(warnings()).toHaveLength(1);
260
+ expect(warnings()[0]).toContain("has not been read yet");
261
+ expect(warnings()[0]).toContain("once per process");
262
+ expect(lapseWarnings()).toEqual([]);
263
+ });
264
+
265
+ test("unreadable: active, one warning (plus the error) however many calls", () => {
266
+ const fake: FakeEnterpriseModule = installFakeEnterpriseModule();
267
+ const readError: Error = new Error("snapshot exploded");
268
+ fake.licensing.getCachedSnapshotError = readError;
269
+
270
+ for (let call: number = 0; call < 25; call++) {
271
+ expect(EnterpriseEdition.isFeatureActive(EnterpriseFeature.SSO)).toBe(
272
+ true,
273
+ );
274
+ }
275
+
276
+ expect(warn).toHaveBeenCalledTimes(2);
277
+ expect(warnings()[0]).toContain("could not read the cached license");
278
+ expect(warn).toHaveBeenCalledWith(readError);
279
+ });
280
+
281
+ test("an unknown state never counts as a lapse, and does not hide a later one", () => {
282
+ const fake: FakeEnterpriseModule = installFakeEnterpriseModule({
283
+ snapshot: createLicenseSnapshotWithStatus("valid"),
284
+ });
285
+
286
+ expect(EnterpriseEdition.isFeatureActive(EnterpriseFeature.SSO)).toBe(true);
287
+
288
+ fake.setSnapshot(null);
289
+ expect(EnterpriseEdition.isFeatureActive(EnterpriseFeature.SSO)).toBe(true);
290
+ expect(lapseWarnings()).toEqual([]);
291
+
292
+ fake.setSnapshot(createLicenseSnapshotWithStatus("expired"));
293
+ expect(EnterpriseEdition.isFeatureActive(EnterpriseFeature.SSO)).toBe(
294
+ false,
295
+ );
296
+ expect(lapseWarnings()).toHaveLength(1);
297
+ });
298
+
299
+ /*
300
+ * An upgraded install's first Enterprise boot whose first-run stamp could
301
+ * not be written (or whose GlobalConfig row does not exist yet): the
302
+ * classifier says "missing" with no graceEndsAt, because it cannot tell
303
+ * when the trial started - so it cannot tell whether the trial is over.
304
+ */
305
+ describe("no license, and the trial start is not recorded yet", () => {
306
+ const unknownTrialStart: () => EnterpriseLicenseSnapshot =
307
+ (): EnterpriseLicenseSnapshot => {
308
+ return createLicenseSnapshotWithStatus("missing", {
309
+ graceEndsAt: undefined,
310
+ });
311
+ };
312
+
313
+ test("is active for every runtime feature, with one warning however many calls", () => {
314
+ installFakeEnterpriseModule({ snapshot: unknownTrialStart() });
315
+
316
+ for (let call: number = 0; call < 25; call++) {
317
+ for (const feature of RUNTIME_ENTERPRISE_FEATURES) {
318
+ expect(EnterpriseEdition.isFeatureActive(feature)).toBe(true);
319
+ }
320
+ }
321
+
322
+ expect(warnings()).toHaveLength(1);
323
+ expect(warnings()[0]).toContain(
324
+ "the start of the 14-day trial has not been recorded yet",
325
+ );
326
+ expect(warnings()[0]).toContain("once per process");
327
+ expect(lapseWarnings()).toEqual([]);
328
+ expect(info).not.toHaveBeenCalled();
329
+ });
330
+
331
+ test("configuration still fails closed", () => {
332
+ installFakeEnterpriseModule({ snapshot: unknownTrialStart() });
333
+
334
+ for (const feature of ALL_ENTERPRISE_FEATURES) {
335
+ expect(EnterpriseEdition.isFeatureAvailableSync(feature)).toBe(false);
336
+ }
337
+ });
338
+
339
+ test("negative control: the same install once the trial is known to be over has lapsed", () => {
340
+ installFakeEnterpriseModule({
341
+ snapshot: createLicenseSnapshotWithStatus("missing", {
342
+ graceEndsAt: new Date(Date.now() - 1000),
343
+ }),
344
+ });
345
+
346
+ for (const feature of RUNTIME_ENTERPRISE_FEATURES) {
347
+ expect(EnterpriseEdition.isFeatureActive(feature)).toBe(false);
348
+ }
349
+
350
+ expect(lapseWarnings()).toHaveLength(1);
351
+ expect(lapseWarnings()[0]).toContain("has lapsed (status: missing)");
352
+ });
353
+
354
+ test("is not reported to listeners, and does not hide a later lapse", () => {
355
+ const fake: FakeEnterpriseModule = installFakeEnterpriseModule({
356
+ snapshot: createLicenseSnapshotWithStatus("valid"),
357
+ });
358
+ const changes: Array<EnterpriseFeatureStateChange> = [];
359
+
360
+ EnterpriseEdition.onFeatureStateChange(
361
+ (change: EnterpriseFeatureStateChange): void => {
362
+ changes.push(change);
363
+ },
364
+ );
365
+
366
+ expect(EnterpriseEdition.isFeatureActive(EnterpriseFeature.SSO)).toBe(
367
+ true,
368
+ );
369
+
370
+ fake.setSnapshot(unknownTrialStart());
371
+ expect(EnterpriseEdition.isFeatureActive(EnterpriseFeature.SSO)).toBe(
372
+ true,
373
+ );
374
+ expect(changes).toEqual([]);
375
+
376
+ fake.setSnapshot(createLicenseSnapshotWithStatus("missing"));
377
+ expect(EnterpriseEdition.isFeatureActive(EnterpriseFeature.SSO)).toBe(
378
+ false,
379
+ );
380
+ expect(changes).toHaveLength(1);
381
+ expect(changes[0]!.stopped).toContain(EnterpriseFeature.SSO);
382
+ });
383
+
384
+ test("billing on never reads it (the Cloud gates by plan)", () => {
385
+ setTestBillingEnabled(true);
386
+ installFakeEnterpriseModule({ snapshot: unknownTrialStart() });
387
+
388
+ expect(EnterpriseEdition.isFeatureActive(EnterpriseFeature.SSO)).toBe(
389
+ true,
390
+ );
391
+ expect(warn).not.toHaveBeenCalled();
392
+ });
393
+ });
394
+
395
+ test("resetForTests forgets the one-time warning (a fresh process warns again)", () => {
396
+ installFakeEnterpriseModule({ snapshot: null });
397
+ EnterpriseEdition.isFeatureActive(EnterpriseFeature.SSO);
398
+
399
+ installFakeEnterpriseModule({ snapshot: null });
400
+ EnterpriseEdition.isFeatureActive(EnterpriseFeature.SSO);
401
+
402
+ expect(warnings()).toHaveLength(2);
403
+ });
404
+ });
405
+
406
+ describe("state changes are logged once per change", () => {
407
+ test("a license that has already lapsed at boot is reported once, naming everything that stopped", () => {
408
+ installFakeEnterpriseModule({
409
+ snapshot: createLicenseSnapshotWithStatus("expired", {
410
+ message: "The license expired on 2026-01-01.",
411
+ }),
412
+ });
413
+
414
+ for (let call: number = 0; call < 10; call++) {
415
+ for (const feature of RUNTIME_ENTERPRISE_FEATURES) {
416
+ expect(EnterpriseEdition.isFeatureActive(feature)).toBe(false);
417
+ }
418
+ }
419
+
420
+ expect(lapseWarnings()).toHaveLength(1);
421
+
422
+ const message: string = lapseWarnings()[0]!;
423
+
424
+ expect(message).toContain(
425
+ "The OneUptime Enterprise license has lapsed (status: expired)",
426
+ );
427
+ expect(message).toContain(
428
+ "single sign-on (SSO), SCIM provisioning and audit logging have stopped until a license is activated",
429
+ );
430
+ expect(message).toContain('"Require SSO for login" is not enforced');
431
+ expect(message).toContain("reset their password");
432
+ expect(message).toContain(
433
+ "License status: The license expired on 2026-01-01.",
434
+ );
435
+ expect(info).not.toHaveBeenCalled();
436
+ });
437
+
438
+ test("a valid license at boot logs nothing", () => {
439
+ installFakeEnterpriseModule();
440
+
441
+ for (const feature of ALL_ENTERPRISE_FEATURES) {
442
+ EnterpriseEdition.isFeatureActive(feature);
443
+ }
444
+
445
+ expect(warn).not.toHaveBeenCalled();
446
+ expect(info).not.toHaveBeenCalled();
447
+ });
448
+
449
+ test("lapse, renewal and lapse again: one warning, one info line, one warning", () => {
450
+ const fake: FakeEnterpriseModule = installFakeEnterpriseModule();
451
+
452
+ EnterpriseEdition.isFeatureActive(EnterpriseFeature.SSO);
453
+ expect(lapseWarnings()).toHaveLength(0);
454
+
455
+ fake.setSnapshot(createLicenseSnapshotWithStatus("missing"));
456
+ EnterpriseEdition.isFeatureActive(EnterpriseFeature.AuditLogs);
457
+ EnterpriseEdition.isFeatureActive(EnterpriseFeature.SSO);
458
+ EnterpriseEdition.isFeatureActive(EnterpriseFeature.SCIM);
459
+ expect(lapseWarnings()).toHaveLength(1);
460
+ expect(lapseWarnings()[0]).toContain("has lapsed (status: missing)");
461
+
462
+ fake.setSnapshot(createLicenseSnapshotWithStatus("valid"));
463
+ EnterpriseEdition.isFeatureActive(EnterpriseFeature.SCIM);
464
+ EnterpriseEdition.isFeatureActive(EnterpriseFeature.SSO);
465
+ expect(infos()).toEqual([
466
+ "The OneUptime Enterprise license covers single sign-on (SSO), SCIM provisioning and audit logging again: they have resumed.",
467
+ ]);
468
+
469
+ fake.setSnapshot(createLicenseSnapshotWithStatus("invalid"));
470
+ EnterpriseEdition.isFeatureActive(EnterpriseFeature.SSO);
471
+ EnterpriseEdition.isFeatureActive(EnterpriseFeature.SSO);
472
+ expect(lapseWarnings()).toHaveLength(2);
473
+ expect(lapseWarnings()[1]).toContain("has lapsed (status: invalid)");
474
+ expect(infos()).toHaveLength(1);
475
+ });
476
+
477
+ test("a license without one feature names only that feature, as not included", () => {
478
+ installFakeEnterpriseModule({
479
+ snapshot: createLicenseSnapshot({
480
+ features: [
481
+ EnterpriseFeature.SSO,
482
+ EnterpriseFeature.AuditLogs,
483
+ EnterpriseFeature.TeamCompliance,
484
+ ],
485
+ }),
486
+ });
487
+
488
+ EnterpriseEdition.isFeatureActive(EnterpriseFeature.SSO);
489
+ expect(lapseWarnings()).toHaveLength(0);
490
+
491
+ EnterpriseEdition.isFeatureActive(EnterpriseFeature.SCIM);
492
+ EnterpriseEdition.isFeatureActive(EnterpriseFeature.SCIM);
493
+
494
+ expect(lapseWarnings()).toEqual([
495
+ "The OneUptime Enterprise license does not include SCIM provisioning: it has stopped until a license that includes it is activated. A master admin can activate or renew the license from the edition label in the Admin Dashboard header.",
496
+ ]);
497
+ });
498
+
499
+ test("billing on never logs a change, whatever the license", () => {
500
+ setTestBillingEnabled(true);
501
+ const fake: FakeEnterpriseModule = installFakeEnterpriseModule({
502
+ snapshot: createLicenseSnapshotWithStatus("expired"),
503
+ });
504
+
505
+ EnterpriseEdition.isFeatureActive(EnterpriseFeature.SSO);
506
+ fake.setSnapshot(createLicenseSnapshotWithStatus("valid"));
507
+ EnterpriseEdition.isFeatureActive(EnterpriseFeature.SSO);
508
+
509
+ expect(warn).not.toHaveBeenCalled();
510
+ expect(info).not.toHaveBeenCalled();
511
+ });
512
+
513
+ test("a logger that throws never changes the answer", () => {
514
+ warn.mockImplementation((): void => {
515
+ throw new Error("log sink down");
516
+ });
517
+ installFakeEnterpriseModule({
518
+ snapshot: createLicenseSnapshotWithStatus("expired"),
519
+ });
520
+
521
+ expect(EnterpriseEdition.isFeatureActive(EnterpriseFeature.SSO)).toBe(
522
+ false,
523
+ );
524
+ expect(EnterpriseEdition.isFeatureActive(EnterpriseFeature.SSO)).toBe(
525
+ false,
526
+ );
527
+ });
528
+ });
529
+
530
+ describe("onFeatureStateChange", () => {
531
+ test("listeners hear each change once, with what stopped and what resumed", () => {
532
+ const fake: FakeEnterpriseModule = installFakeEnterpriseModule();
533
+ const changes: Array<EnterpriseFeatureStateChange> = [];
534
+
535
+ EnterpriseEdition.onFeatureStateChange(
536
+ (change: EnterpriseFeatureStateChange): void => {
537
+ changes.push(change);
538
+ },
539
+ );
540
+
541
+ EnterpriseEdition.isFeatureActive(EnterpriseFeature.SSO);
542
+ expect(changes).toHaveLength(0);
543
+
544
+ const lapsed: EnterpriseLicenseSnapshot =
545
+ createLicenseSnapshotWithStatus("expired");
546
+ fake.setSnapshot(lapsed);
547
+
548
+ for (const feature of RUNTIME_ENTERPRISE_FEATURES) {
549
+ EnterpriseEdition.isFeatureActive(feature);
550
+ EnterpriseEdition.isFeatureActive(feature);
551
+ }
552
+
553
+ expect(changes).toEqual([
554
+ {
555
+ stopped: [
556
+ EnterpriseFeature.SSO,
557
+ EnterpriseFeature.SCIM,
558
+ EnterpriseFeature.AuditLogs,
559
+ ],
560
+ resumed: [],
561
+ snapshot: lapsed,
562
+ },
563
+ ]);
564
+
565
+ fake.setSnapshot(createLicenseSnapshotWithStatus("valid"));
566
+ EnterpriseEdition.isFeatureActive(EnterpriseFeature.SCIM);
567
+
568
+ expect(changes).toHaveLength(2);
569
+ expect(changes[1]!.stopped).toEqual([]);
570
+ expect(changes[1]!.resumed).toEqual([
571
+ EnterpriseFeature.SSO,
572
+ EnterpriseFeature.SCIM,
573
+ EnterpriseFeature.AuditLogs,
574
+ ]);
575
+ });
576
+
577
+ test("a listener that throws is logged and never breaks the check or the other listeners", () => {
578
+ installFakeEnterpriseModule({
579
+ snapshot: createLicenseSnapshotWithStatus("expired"),
580
+ });
581
+ const heard: Array<string> = [];
582
+
583
+ EnterpriseEdition.onFeatureStateChange((): void => {
584
+ throw new Error("listener exploded");
585
+ });
586
+ EnterpriseEdition.onFeatureStateChange((): void => {
587
+ heard.push("second");
588
+ });
589
+
590
+ expect(EnterpriseEdition.isFeatureActive(EnterpriseFeature.SSO)).toBe(
591
+ false,
592
+ );
593
+ expect(heard).toEqual(["second"]);
594
+ expect(error).toHaveBeenCalled();
595
+ });
596
+
597
+ test("the returned function removes the listener", () => {
598
+ const fake: FakeEnterpriseModule = installFakeEnterpriseModule();
599
+ const heard: Array<EnterpriseFeatureStateChange> = [];
600
+
601
+ const stop: () => void = EnterpriseEdition.onFeatureStateChange(
602
+ (change: EnterpriseFeatureStateChange): void => {
603
+ heard.push(change);
604
+ },
605
+ );
606
+ stop();
607
+
608
+ fake.setSnapshot(createLicenseSnapshotWithStatus("expired"));
609
+ EnterpriseEdition.isFeatureActive(EnterpriseFeature.SSO);
610
+
611
+ expect(heard).toEqual([]);
612
+ });
613
+ });
614
+
615
+ describe("describeStoppedFeatures / describeResumedFeatures", () => {
616
+ test("nothing stopped or resumed is no line at all", () => {
617
+ expect(
618
+ EnterpriseEdition.describeStoppedFeatures(
619
+ [],
620
+ createLicenseSnapshotWithStatus("expired"),
621
+ ),
622
+ ).toBeNull();
623
+ expect(EnterpriseEdition.describeResumedFeatures([])).toBeNull();
624
+ });
625
+
626
+ test("audit logging alone does not mention SSO enforcement", () => {
627
+ const message: string | null = EnterpriseEdition.describeStoppedFeatures(
628
+ [EnterpriseFeature.AuditLogs],
629
+ createLicenseSnapshotWithStatus("expired"),
630
+ );
631
+
632
+ expect(message).toContain("audit logging has stopped");
633
+ expect(message).not.toContain("Require SSO");
634
+ });
635
+
636
+ test("one resumed feature reads in the singular", () => {
637
+ expect(
638
+ EnterpriseEdition.describeResumedFeatures([EnterpriseFeature.SSO]),
639
+ ).toBe(
640
+ "The OneUptime Enterprise license covers single sign-on (SSO) again: it has resumed.",
641
+ );
642
+ });
643
+ });