@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,319 @@
1
+ import "@testing-library/jest-dom";
2
+ import {
3
+ afterEach,
4
+ beforeEach,
5
+ describe,
6
+ expect,
7
+ jest,
8
+ test,
9
+ } from "@jest/globals";
10
+ import { cleanup, render, screen } from "@testing-library/react";
11
+ import React, { FunctionComponent, ReactElement } from "react";
12
+
13
+ /*
14
+ * The six identity pages the Dashboard routes to - Settings > SSO / OIDC /
15
+ * SCIM and Status page > SSO / OIDC / SCIM - are Enterprise Edition screens
16
+ * (ee/Dashboard/SSO). Core keeps a shell at each page's original path, so the
17
+ * route files and the lazy page map never changed: the shell renders the
18
+ * Enterprise screen when the project may use the feature AND the bundle
19
+ * includes it, and the upsell card the page used to show otherwise.
20
+ *
21
+ * "@oneuptime/ee-dashboard" is replaced by a plugin object the tests fill in,
22
+ * standing in for the Enterprise bundle; left empty it is the Community
23
+ * bundle. Billing, the edition and the plan are pinned in every test: CI's
24
+ * config.env sets BILLING_ENABLED=true.
25
+ */
26
+
27
+ let billingEnabledForTest: boolean = false;
28
+ let enterpriseEditionForTest: boolean = false;
29
+ let currentPlanForTest: string | null = null;
30
+
31
+ const CLOUD_PLAN_ENV: Record<string, string> = {
32
+ SUBSCRIPTION_PLAN_BASIC: "Free,priceMonthlyId1,priceYearlyId1,0,0,1,0",
33
+ SUBSCRIPTION_PLAN_GROWTH: "Growth,priceMonthlyId2,priceYearlyId2,0,0,2,14",
34
+ SUBSCRIPTION_PLAN_SCALE: "Scale,priceMonthlyId3,priceYearlyId3,0,0,3,0",
35
+ SUBSCRIPTION_PLAN_ENTERPRISE:
36
+ "Enterprise,priceMonthlyId4,priceYearlyId4,-1,-1,4,14",
37
+ };
38
+
39
+ jest.mock("../../../UI/Config", () => {
40
+ const actual: Record<string, unknown> = jest.requireActual(
41
+ "../../../UI/Config",
42
+ ) as Record<string, unknown>;
43
+
44
+ const mocked: Record<string, unknown> = { ...actual };
45
+
46
+ Object.defineProperty(mocked, "BILLING_ENABLED", {
47
+ get: (): boolean => {
48
+ return billingEnabledForTest;
49
+ },
50
+ });
51
+
52
+ Object.defineProperty(mocked, "IS_ENTERPRISE_EDITION", {
53
+ get: (): boolean => {
54
+ return enterpriseEditionForTest;
55
+ },
56
+ });
57
+
58
+ mocked["getAllEnvVars"] = (): Record<string, string> => {
59
+ return CLOUD_PLAN_ENV;
60
+ };
61
+
62
+ return mocked;
63
+ });
64
+
65
+ jest.mock("../../../UI/Utils/Project", () => {
66
+ const actual: Record<string, any> = jest.requireActual(
67
+ "../../../UI/Utils/Project",
68
+ ) as Record<string, any>;
69
+
70
+ return {
71
+ __esModule: true,
72
+ ...actual,
73
+ default: {
74
+ ...actual["default"],
75
+ getCurrentPlan: (): string | null => {
76
+ return currentPlanForTest;
77
+ },
78
+ },
79
+ };
80
+ });
81
+
82
+ /*
83
+ * What getDashboardPlugins() returns in this suite. The shells read it on
84
+ * every render, so each test fills it in after the shells were imported.
85
+ */
86
+ const mockEnterprisePlugins: Record<string, unknown> = {};
87
+
88
+ jest.mock("@oneuptime/ee-dashboard", () => {
89
+ return { __esModule: true, default: mockEnterprisePlugins };
90
+ });
91
+
92
+ import SettingsOIDC from "../../../../App/FeatureSet/Dashboard/src/Pages/Settings/OIDC";
93
+ import SettingsSCIM from "../../../../App/FeatureSet/Dashboard/src/Pages/Settings/SCIM";
94
+ import SettingsSSO from "../../../../App/FeatureSet/Dashboard/src/Pages/Settings/SSO";
95
+ import StatusPageViewOIDC from "../../../../App/FeatureSet/Dashboard/src/Pages/StatusPages/View/OIDC";
96
+ import StatusPageViewSCIM from "../../../../App/FeatureSet/Dashboard/src/Pages/StatusPages/View/SCIM";
97
+ import StatusPageViewSSO from "../../../../App/FeatureSet/Dashboard/src/Pages/StatusPages/View/SSO";
98
+ import PageComponentProps from "../../../../App/FeatureSet/Dashboard/src/Pages/PageComponentProps";
99
+ import { DashboardEnterprisePluginKey } from "../../../../App/FeatureSet/Dashboard/src/Enterprise/EnterprisePlugins";
100
+ import Route from "../../../Types/API/Route";
101
+ import { PlanType } from "../../../Types/Billing/SubscriptionPlan";
102
+
103
+ interface ShellCase {
104
+ name: string;
105
+ Shell: FunctionComponent<PageComponentProps>;
106
+ pluginKey: DashboardEnterprisePluginKey;
107
+ // The upsell copy the page showed before it moved to ee/.
108
+ upsellTitle: string;
109
+ featureName: string;
110
+ }
111
+
112
+ const SHELLS: Array<ShellCase> = [
113
+ {
114
+ name: "Settings > SSO",
115
+ Shell: SettingsSSO,
116
+ pluginKey: "SettingsSSO",
117
+ upsellTitle: "Single Sign On (SSO)",
118
+ featureName: "SAML Single Sign On",
119
+ },
120
+ {
121
+ name: "Settings > OIDC",
122
+ Shell: SettingsOIDC,
123
+ pluginKey: "SettingsOIDC",
124
+ upsellTitle: "OpenID Connect (OIDC)",
125
+ featureName: "OIDC Single Sign On",
126
+ },
127
+ {
128
+ name: "Settings > SCIM",
129
+ Shell: SettingsSCIM,
130
+ pluginKey: "SettingsSCIM",
131
+ upsellTitle: "SCIM User Provisioning",
132
+ featureName: "SCIM User Provisioning",
133
+ },
134
+ {
135
+ name: "Status page > SSO",
136
+ Shell: StatusPageViewSSO,
137
+ pluginKey: "StatusPageSSO",
138
+ upsellTitle: "Status Page SSO",
139
+ featureName: "Status Page SAML SSO",
140
+ },
141
+ {
142
+ name: "Status page > OIDC",
143
+ Shell: StatusPageViewOIDC,
144
+ pluginKey: "StatusPageOIDC",
145
+ upsellTitle: "Status Page OIDC",
146
+ featureName: "Status Page OIDC SSO",
147
+ },
148
+ {
149
+ name: "Status page > SCIM",
150
+ Shell: StatusPageViewSCIM,
151
+ pluginKey: "StatusPageSCIM",
152
+ upsellTitle: "Status Page SCIM",
153
+ featureName: "Status Page SCIM Provisioning",
154
+ },
155
+ ];
156
+
157
+ const PAGE_PROPS: PageComponentProps = {
158
+ pageRoute: new Route("/dashboard/project-id/settings/identity"),
159
+ currentProject: null,
160
+ hasPaymentMethod: true,
161
+ };
162
+
163
+ /*
164
+ * Stands in for an Enterprise screen: says which plugin key it is and echoes
165
+ * the props the shell handed it.
166
+ */
167
+ const makeFakeScreen: (
168
+ pluginKey: string,
169
+ ) => FunctionComponent<PageComponentProps> = (
170
+ pluginKey: string,
171
+ ): FunctionComponent<PageComponentProps> => {
172
+ const FakeScreen: FunctionComponent<PageComponentProps> = (
173
+ props: PageComponentProps,
174
+ ): ReactElement => {
175
+ return (
176
+ <div data-testid="enterprise-screen">
177
+ {pluginKey}|{props.pageRoute.toString()}|
178
+ {String(props.hasPaymentMethod)}
179
+ </div>
180
+ );
181
+ };
182
+
183
+ return FakeScreen;
184
+ };
185
+
186
+ const installPlugins: (keys: Array<DashboardEnterprisePluginKey>) => void = (
187
+ keys: Array<DashboardEnterprisePluginKey>,
188
+ ): void => {
189
+ for (const key of keys) {
190
+ mockEnterprisePlugins[key] = makeFakeScreen(key);
191
+ }
192
+ };
193
+
194
+ const clearPlugins: () => void = (): void => {
195
+ for (const key of Object.keys(mockEnterprisePlugins)) {
196
+ delete mockEnterprisePlugins[key];
197
+ }
198
+ };
199
+
200
+ beforeEach(() => {
201
+ billingEnabledForTest = false;
202
+ enterpriseEditionForTest = false;
203
+ currentPlanForTest = null;
204
+ clearPlugins();
205
+ });
206
+
207
+ afterEach(() => {
208
+ cleanup();
209
+ clearPlugins();
210
+ });
211
+
212
+ describe.each(SHELLS)("$name shell", (shell: ShellCase) => {
213
+ test("Community Edition: the upsell card, even when a plugin is present", () => {
214
+ installPlugins([shell.pluginKey]);
215
+
216
+ render(<shell.Shell {...PAGE_PROPS} />);
217
+
218
+ expect(screen.getAllByText(shell.featureName).length).toBeGreaterThan(0);
219
+ expect(screen.getAllByText(shell.upsellTitle).length).toBeGreaterThan(0);
220
+ expect(
221
+ screen.getAllByText("Learn about Enterprise Edition").length,
222
+ ).toBeGreaterThan(0);
223
+ expect(screen.queryByTestId("enterprise-screen")).not.toBeInTheDocument();
224
+ });
225
+
226
+ test("Enterprise Edition: the Enterprise screen, with the page props", () => {
227
+ enterpriseEditionForTest = true;
228
+ installPlugins([shell.pluginKey]);
229
+
230
+ render(<shell.Shell {...PAGE_PROPS} />);
231
+
232
+ expect(screen.getByTestId("enterprise-screen")).toHaveTextContent(
233
+ `${shell.pluginKey}|/dashboard/project-id/settings/identity|true`,
234
+ );
235
+ expect(screen.queryByText(shell.featureName)).not.toBeInTheDocument();
236
+ });
237
+
238
+ test("Enterprise Edition on a Community bundle: the upsell, pointing at the edition", () => {
239
+ enterpriseEditionForTest = true;
240
+
241
+ render(<shell.Shell {...PAGE_PROPS} />);
242
+
243
+ expect(screen.getAllByText(shell.featureName).length).toBeGreaterThan(0);
244
+ expect(
245
+ screen.getAllByText("Learn about Enterprise Edition").length,
246
+ ).toBeGreaterThan(0);
247
+ expect(screen.queryByText("Upgrade to Scale")).not.toBeInTheDocument();
248
+ });
249
+
250
+ test("OneUptime Cloud below Scale: the plan upsell, never the screen", () => {
251
+ billingEnabledForTest = true;
252
+ enterpriseEditionForTest = true;
253
+ currentPlanForTest = PlanType.Growth;
254
+ installPlugins([shell.pluginKey]);
255
+
256
+ render(<shell.Shell {...PAGE_PROPS} />);
257
+
258
+ expect(screen.getAllByText("Upgrade to Scale").length).toBeGreaterThan(0);
259
+ expect(screen.getAllByText(shell.featureName).length).toBeGreaterThan(0);
260
+ expect(screen.queryByTestId("enterprise-screen")).not.toBeInTheDocument();
261
+ });
262
+
263
+ test.each([PlanType.Scale, PlanType.Enterprise])(
264
+ "OneUptime Cloud on %s: the Enterprise screen",
265
+ (plan: PlanType) => {
266
+ billingEnabledForTest = true;
267
+ enterpriseEditionForTest = true;
268
+ currentPlanForTest = plan;
269
+ installPlugins([shell.pluginKey]);
270
+
271
+ render(<shell.Shell {...PAGE_PROPS} />);
272
+
273
+ expect(screen.getByTestId("enterprise-screen")).toHaveTextContent(
274
+ shell.pluginKey,
275
+ );
276
+ },
277
+ );
278
+
279
+ test("renders its own plugin key when every identity screen is present", () => {
280
+ enterpriseEditionForTest = true;
281
+ installPlugins(
282
+ SHELLS.map((each: ShellCase) => {
283
+ return each.pluginKey;
284
+ }),
285
+ );
286
+
287
+ render(<shell.Shell {...PAGE_PROPS} />);
288
+
289
+ expect(screen.getByTestId("enterprise-screen")).toHaveTextContent(
290
+ `${shell.pluginKey}|`,
291
+ );
292
+ });
293
+
294
+ test("ignores other features' screens", () => {
295
+ enterpriseEditionForTest = true;
296
+ installPlugins(
297
+ SHELLS.map((each: ShellCase) => {
298
+ return each.pluginKey;
299
+ }).filter((key: DashboardEnterprisePluginKey) => {
300
+ return key !== shell.pluginKey;
301
+ }),
302
+ );
303
+
304
+ render(<shell.Shell {...PAGE_PROPS} />);
305
+
306
+ expect(screen.queryByTestId("enterprise-screen")).not.toBeInTheDocument();
307
+ expect(screen.getAllByText(shell.featureName).length).toBeGreaterThan(0);
308
+ });
309
+ });
310
+
311
+ describe("identity shells", () => {
312
+ test("each reads a different plugin key", () => {
313
+ const keys: Array<string> = SHELLS.map((shell: ShellCase) => {
314
+ return shell.pluginKey;
315
+ });
316
+
317
+ expect(new Set(keys).size).toBe(SHELLS.length);
318
+ });
319
+ });
@@ -0,0 +1,185 @@
1
+ import "@testing-library/jest-dom";
2
+ import {
3
+ act,
4
+ cleanup,
5
+ fireEvent,
6
+ render,
7
+ screen,
8
+ } from "@testing-library/react";
9
+ import React, { ReactElement, useEffect } from "react";
10
+ import {
11
+ afterEach,
12
+ beforeEach,
13
+ describe,
14
+ expect,
15
+ jest,
16
+ test,
17
+ } from "@jest/globals";
18
+ import ProjectUtil from "../../../UI/Utils/Project";
19
+ import Navigation from "../../../UI/Utils/Navigation";
20
+ import ObjectID from "../../../Types/ObjectID";
21
+ import Route from "../../../Types/API/Route";
22
+ import URL from "../../../Types/API/URL";
23
+ import OnboardingSsoPage from "../../../../App/FeatureSet/Dashboard/src/Pages/Onboarding/SSO";
24
+ import PageMap from "../../../../App/FeatureSet/Dashboard/src/Utils/PageMap";
25
+ import RouteMap from "../../../../App/FeatureSet/Dashboard/src/Utils/RouteMap";
26
+ import { getJestSpyOn } from "../../Spy";
27
+
28
+ /*
29
+ * Dashboard > project SSO sign-in (Onboarding/SSO): where a user lands when a
30
+ * project requires SSO. It lists the project's providers from
31
+ * /project-sso/:projectId/sso-list.
32
+ *
33
+ * That list is empty when the project has no enabled provider - and always on
34
+ * the Community Edition, where SSO login is part of the Enterprise Edition and
35
+ * the server lists no providers. The page must then explain why and offer a
36
+ * way back to sign-in, rather than a dead end.
37
+ */
38
+
39
+ type ProviderRow = { _id: string; name: string };
40
+
41
+ interface ProviderListProps {
42
+ id: string;
43
+ overrideFetchApiUrl: URL;
44
+ noItemsMessage: string;
45
+ onListLoaded?: (list: Array<ProviderRow>) => void;
46
+ onSelectChange?: (list: Array<ProviderRow>) => void;
47
+ }
48
+
49
+ let providersForTest: Array<ProviderRow> = [];
50
+
51
+ /*
52
+ * The real ModelList fetches over HTTP; this stand-in "loads" the configured
53
+ * providers the same way (onListLoaded after mount) and renders them.
54
+ */
55
+ jest.mock("../../../UI/Components/ModelList/ModelList", () => {
56
+ return {
57
+ __esModule: true,
58
+ default: (props: ProviderListProps): ReactElement => {
59
+ useEffect(() => {
60
+ props.onListLoaded?.(providersForTest);
61
+ }, []);
62
+
63
+ return (
64
+ <div
65
+ data-testid={props.id}
66
+ data-fetch-url={props.overrideFetchApiUrl.toString()}
67
+ >
68
+ {providersForTest.length === 0 ? (
69
+ <p>{props.noItemsMessage}</p>
70
+ ) : (
71
+ providersForTest.map((provider: ProviderRow) => {
72
+ return (
73
+ <button
74
+ key={provider._id}
75
+ onClick={() => {
76
+ props.onSelectChange?.([provider]);
77
+ }}
78
+ >
79
+ {provider.name}
80
+ </button>
81
+ );
82
+ })
83
+ )}
84
+ </div>
85
+ );
86
+ },
87
+ };
88
+ });
89
+
90
+ jest.mock("../../../UI/Components/Page/Page", () => {
91
+ const react: typeof React = jest.requireActual("react") as typeof React;
92
+
93
+ return {
94
+ __esModule: true,
95
+ default: (props: { children?: React.ReactNode }) => {
96
+ return react.createElement("div", null, props.children);
97
+ },
98
+ };
99
+ });
100
+
101
+ const PROJECT_ID: ObjectID = new ObjectID(
102
+ "11111111-1111-4111-8111-111111111111",
103
+ );
104
+
105
+ const renderPage: () => Promise<void> = async (): Promise<void> => {
106
+ await act(async () => {
107
+ render(
108
+ <OnboardingSsoPage
109
+ pageRoute={new Route("/dashboard/project/sso")}
110
+ currentProject={null}
111
+ hasPaymentMethod={false}
112
+ />,
113
+ );
114
+ });
115
+ };
116
+
117
+ describe("Dashboard project SSO sign-in page", () => {
118
+ beforeEach(() => {
119
+ providersForTest = [];
120
+ getJestSpyOn(ProjectUtil, "getCurrentProjectId").mockReturnValue(
121
+ PROJECT_ID,
122
+ );
123
+ });
124
+
125
+ afterEach(() => {
126
+ cleanup();
127
+ jest.restoreAllMocks();
128
+ });
129
+
130
+ test("with no provider (always the case on the Community Edition) it explains why and links back to sign-in", async () => {
131
+ await renderPage();
132
+
133
+ const help: HTMLElement = await screen.findByTestId(
134
+ "sso-no-providers-help",
135
+ );
136
+
137
+ expect(help).toHaveTextContent(
138
+ "This project has no single sign-on provider you can use to log in.",
139
+ );
140
+ expect(help).toHaveTextContent(
141
+ "Single sign-on is part of the OneUptime Enterprise Edition",
142
+ );
143
+ expect(help).toHaveTextContent(
144
+ "sign in with your email and password instead",
145
+ );
146
+
147
+ const backToSignIn: HTMLElement = screen.getByText("Back to sign in");
148
+
149
+ expect(backToSignIn.closest("a")).toHaveAttribute(
150
+ "href",
151
+ RouteMap[PageMap.LOGOUT]!.toString(),
152
+ );
153
+ });
154
+
155
+ test("with providers it lists them, shows no help text, and signs in with the chosen one", async () => {
156
+ providersForTest = [
157
+ { _id: "22222222-2222-4222-8222-222222222222", name: "Okta" },
158
+ ];
159
+ const navigate: ReturnType<typeof getJestSpyOn> = getJestSpyOn(
160
+ Navigation,
161
+ "navigate",
162
+ ).mockImplementation(() => {});
163
+
164
+ await renderPage();
165
+
166
+ expect(
167
+ screen.queryByTestId("sso-no-providers-help"),
168
+ ).not.toBeInTheDocument();
169
+
170
+ fireEvent.click(screen.getByText("Okta"));
171
+
172
+ expect(navigate).toHaveBeenCalledTimes(1);
173
+ expect(String(navigate.mock.calls[0]![0])).toContain(
174
+ `/sso/${PROJECT_ID.toString()}/22222222-2222-4222-8222-222222222222`,
175
+ );
176
+ });
177
+
178
+ test("lists providers from the project's sso-list endpoint", async () => {
179
+ await renderPage();
180
+
181
+ expect(
182
+ screen.getByTestId("sso-list").getAttribute("data-fetch-url"),
183
+ ).toContain(`/project-sso/${PROJECT_ID.toString()}/sso-list`);
184
+ });
185
+ });
@@ -48,7 +48,6 @@ import ListResult from "../../../Types/BaseDatabase/ListResult";
48
48
  import RangeStartAndEndDateTime from "../../../Types/Time/RangeStartAndEndDateTime";
49
49
  import TimeRange from "../../../Types/Time/TimeRange";
50
50
  import { JSONObject } from "../../../Types/JSON";
51
- import JSONFunctions from "../../../Types/JSONFunctions";
52
51
  import ObjectID from "../../../Types/ObjectID";
53
52
  import {
54
53
  SecurityConnectorSample,
@@ -269,12 +268,36 @@ function eventsParams(route: Route): URLSearchParams {
269
268
  return new URLSearchParams(text.slice(text.indexOf("?")));
270
269
  }
271
270
 
272
- // The table's own filter on the link; {} when the link sets none.
271
+ /*
272
+ * The chips the link opens the events explorer with, re-shaped as
273
+ * `{ attributes: { key: value } }` — the reading these assertions have always
274
+ * used.
275
+ *
276
+ * The link's grammar is the explorers' own `filters` param
277
+ * (`[["attributes.<key>", "<value>"], ...]`); it used to be the model
278
+ * table's serialized column filter, which went away with the table. Anything
279
+ * the explorer does not express as an attribute chip is left out, so an
280
+ * assertion that a key is absent still means "the link does not filter on
281
+ * it".
282
+ */
273
283
  function eventsFilter(route: Route): JSONObject {
274
- const raw: string | null = eventsParams(route).get(
275
- "security-events-table-filter",
276
- );
277
- return raw ? JSONFunctions.deserialize(JSON.parse(raw) as JSONObject) : {};
284
+ const raw: string | null = eventsParams(route).get("filters");
285
+
286
+ if (!raw) {
287
+ return {};
288
+ }
289
+
290
+ const attributes: JSONObject = {};
291
+
292
+ for (const pair of JSON.parse(raw) as Array<[string, string]>) {
293
+ if (!Array.isArray(pair) || !pair[0]?.startsWith("attributes.")) {
294
+ continue;
295
+ }
296
+
297
+ attributes[pair[0].substring("attributes.".length)] = pair[1];
298
+ }
299
+
300
+ return Object.keys(attributes).length > 0 ? { attributes } : {};
278
301
  }
279
302
 
280
303
  /*
@@ -1481,25 +1504,38 @@ describe("View events for a connection run", () => {
1481
1504
  expect(eventsFilter(route)["attributes"]).toBeUndefined();
1482
1505
  });
1483
1506
 
1484
- test("the window is the page's time range, not a table filter", (): void => {
1507
+ test("the window is the page's time range, not a chip", (): void => {
1485
1508
  const route: Route = connectionEventsRoute(result(), CONNECTION_ID);
1486
1509
  const params: URLSearchParams = eventsParams(route);
1487
1510
 
1488
1511
  expect(params.get("range")).toBe(TimeRange.CUSTOM);
1489
1512
  expect(params.get("start")).toBe("2026-09-09T01:30:29.000Z");
1490
1513
  expect(params.get("end")).toBe("2026-09-09T01:30:31.000Z");
1491
- // The table no longer offers a Time filter, so none is written for it.
1514
+ // The window is the explorer's own range, never one of its chips.
1492
1515
  expect(eventsFilter(route)["time"]).toBeUndefined();
1493
1516
  expect(eventsFilter(route)["attributes"]).toEqual({
1494
1517
  [SECURITY_CONNECTION_ID_ATTRIBUTE]: CONNECTION_ID,
1495
1518
  });
1496
1519
  });
1497
1520
 
1498
- test("a link with nothing to filter on sets no table filter at all", (): void => {
1521
+ test("the connection chip is written in the explorer's filters grammar", (): void => {
1522
+ const raw: string | null = eventsParams(
1523
+ connectionEventsRoute(result(), CONNECTION_ID),
1524
+ ).get("filters");
1525
+
1526
+ expect(raw).not.toBeNull();
1527
+ expect(JSON.parse(raw as string)).toEqual([
1528
+ [`attributes.${SECURITY_CONNECTION_ID_ATTRIBUTE}`, CONNECTION_ID],
1529
+ ]);
1530
+ });
1531
+
1532
+ test("a link with nothing to filter on sets no chips at all", (): void => {
1499
1533
  const params: URLSearchParams = eventsParams(
1500
1534
  connectionEventsRoute(result()),
1501
1535
  );
1502
1536
 
1537
+ expect(params.get("filters")).toBeNull();
1538
+ // The retired model table's own filter param is gone for good.
1503
1539
  expect(params.get("security-events-table-filter")).toBeNull();
1504
1540
  expect(params.get("range")).toBe(TimeRange.CUSTOM);
1505
1541
  });