@oneuptime/common 13.0.7 → 13.0.8

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 (463) hide show
  1. package/Models/DatabaseModels/OnCallDutyPolicyScheduleCalendarFeed.ts +1 -1
  2. package/Models/DatabaseModels/ProjectOnCallCalendarFeed.ts +1 -1
  3. package/Models/DatabaseModels/UserOnCallCalendarFeed.ts +1 -1
  4. package/Server/API/AIBillingAPI.ts +1 -0
  5. package/Server/API/AIInsightAPI.ts +1 -4
  6. package/Server/API/AIInvestigationAPI.ts +1 -4
  7. package/Server/API/AIReadinessAPI.ts +4 -5
  8. package/Server/API/AlertAPI.ts +1 -0
  9. package/Server/API/AutoRemediationAPI.ts +1 -4
  10. package/Server/API/BaseAPI.ts +13 -0
  11. package/Server/API/BaseAnalyticsAPI.ts +80 -9
  12. package/Server/API/BillingAPI.ts +2 -0
  13. package/Server/API/BillingInvoiceAPI.ts +1 -0
  14. package/Server/API/BillingPaymentMethodAPI.ts +2 -0
  15. package/Server/API/CodeFixRunAPI.ts +1 -3
  16. package/Server/API/CommonAPI.ts +68 -4
  17. package/Server/API/DashboardAPI.ts +12 -12
  18. package/Server/API/GlobalConfigAPI.ts +17 -0
  19. package/Server/API/IncidentAPI.ts +2 -0
  20. package/Server/API/IncidentEpisodeAPI.ts +1 -0
  21. package/Server/API/NotificationAPI.ts +1 -0
  22. package/Server/API/OnCallCalendarAPI.ts +4 -5
  23. package/Server/API/OnCallDutyPolicyAPI.ts +7 -0
  24. package/Server/API/OnCallReadinessAPI.ts +4 -1
  25. package/Server/API/OnCallScheduleTimelineAPI.ts +731 -0
  26. package/Server/API/ProjectAPI.ts +1 -0
  27. package/Server/API/ScheduledMaintenanceAPI.ts +1 -0
  28. package/Server/API/StatusPageAPI.ts +161 -32
  29. package/Server/API/TeamMemberAPI.ts +3 -0
  30. package/Server/API/UserCallAPI.ts +2 -0
  31. package/Server/API/UserEmailAPI.ts +2 -0
  32. package/Server/API/UserIncomingCallNumberAPI.ts +2 -0
  33. package/Server/API/UserMicrosoftTeamsAPI.ts +1 -0
  34. package/Server/API/UserSlackAPI.ts +1 -0
  35. package/Server/API/UserSmsAPI.ts +2 -0
  36. package/Server/API/UserTotpAuthAPI.ts +1 -0
  37. package/Server/API/UserWebAuthnAPI.ts +2 -0
  38. package/Server/API/UserWebhookAPI.ts +1 -0
  39. package/Server/API/UserWhatsAppAPI.ts +2 -0
  40. package/Server/Middleware/MasterAdminAuthorization.ts +13 -2
  41. package/Server/Middleware/UserAuthorization.ts +79 -5
  42. package/Server/Services/ApiKeyPermissionService.ts +101 -4
  43. package/Server/Services/DatabaseService.ts +245 -0
  44. package/Server/Services/DetectionRuleService.ts +5 -4
  45. package/Server/Services/OnCallDutyPolicyChildService.ts +261 -0
  46. package/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.ts +2 -2
  47. package/Server/Services/OnCallDutyPolicyEscalationRuleService.ts +2 -2
  48. package/Server/Services/OnCallDutyPolicyEscalationRuleTeamService.ts +2 -2
  49. package/Server/Services/OnCallDutyPolicyEscalationRuleUserService.ts +2 -2
  50. package/Server/Services/PayAsYouGoBillingService.ts +23 -28
  51. package/Server/Services/ProjectService.ts +18 -0
  52. package/Server/Services/RumSessionPinService.ts +274 -22
  53. package/Server/Services/TeamPermissionService.ts +120 -26
  54. package/Server/Services/ThreatIntelFeedService.ts +6 -3
  55. package/Server/Types/Database/Permissions/BasePermission.ts +9 -7
  56. package/Server/Types/Database/Permissions/Index.ts +75 -11
  57. package/Server/Types/Database/Permissions/TablePermission.ts +24 -28
  58. package/Server/Utils/AI/AIChatPrivacyFilter.ts +8 -0
  59. package/Server/Utils/AI/AIRunPrivacyFilter.ts +8 -0
  60. package/Server/Utils/MasterAdminPageAccess.ts +61 -0
  61. package/Server/Utils/Monitor/MonitorAlert.ts +3 -1
  62. package/Server/Utils/Monitor/MonitorIncident.ts +3 -1
  63. package/Server/Utils/OnCall/OnCallCalendarFeedRenderer.ts +1 -1
  64. package/Server/Utils/Realtime.ts +163 -45
  65. package/Server/Utils/SecurityEvent/DetectionRuleEvaluator.ts +11 -28
  66. package/Server/Utils/SecurityEvent/GoogleSecOpsSeverityRepair.ts +170 -0
  67. package/Server/Utils/SecurityEvent/Sigma/SigmaClickhouseCompiler.ts +1 -1
  68. package/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelFeedPoller.ts +6 -2
  69. package/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelMatcher.ts +10 -9
  70. package/Tests/App/Dashboard/AffectedResourcesPicker.test.tsx +1059 -0
  71. package/Tests/App/Dashboard/AffectedResourcesPickerEditForm.test.tsx +376 -0
  72. package/Tests/App/Dashboard/AffectedResourcesPickerHiddenTypes.test.tsx +757 -0
  73. package/Tests/App/Dashboard/AffectedResourcesSummaryStep.test.tsx +307 -0
  74. package/Tests/App/Dashboard/ArgumentsFormGroupByUnlistedAttributes.test.tsx +131 -0
  75. package/Tests/App/Dashboard/DashboardHeaderRequests.test.tsx +1 -1
  76. package/Tests/App/Dashboard/DashboardMonitorLabelVariable.test.tsx +9 -1
  77. package/Tests/App/Dashboard/DashboardVariableAllContract.test.tsx +24 -0
  78. package/Tests/App/Dashboard/DashboardVariableSelector.test.tsx +162 -8
  79. package/Tests/App/Dashboard/EntityFilterDropdownArchivedSlos.test.tsx +105 -6
  80. package/Tests/App/Dashboard/EntityFilterDropdownUnlistedSelection.test.tsx +434 -0
  81. package/Tests/App/Dashboard/EscalationRuleReadiness.test.tsx +276 -1
  82. package/Tests/App/Dashboard/OnCallCalendarFeedSideMenus.test.tsx +9 -1
  83. package/Tests/App/Dashboard/PayAsYouGoConsentGate.test.tsx +58 -42
  84. package/Tests/App/Dashboard/PayAsYouGoNotices.test.tsx +42 -5
  85. package/Tests/App/Dashboard/ResourceAuditLogsSideMenus.test.tsx +34 -23
  86. package/Tests/App/Dashboard/ScheduleTimeline.test.tsx +1580 -0
  87. package/Tests/App/Dashboard/ScheduleTimelineAPI.test.ts +280 -0
  88. package/Tests/App/Dashboard/ScheduleTimelineModel.test.ts +673 -0
  89. package/Tests/App/Dashboard/SecurityEventConnectionDiagnostics.test.tsx +95 -68
  90. package/Tests/App/Dashboard/SecurityEventsDetectionRulesPage.test.tsx +86 -3
  91. package/Tests/App/Dashboard/SecurityEventsEmptyState.test.tsx +28 -3
  92. package/Tests/App/Dashboard/SecurityEventsExplorer.test.tsx +761 -0
  93. package/Tests/App/Dashboard/SecurityEventsGuideContent.test.ts +1313 -0
  94. package/Tests/App/Dashboard/SecurityEventsHowItWorksCard.test.tsx +536 -0
  95. package/Tests/App/Dashboard/SecurityEventsNoResults.test.tsx +222 -0
  96. package/Tests/App/Dashboard/SecurityEventsThreatIntelPage.test.tsx +199 -0
  97. package/Tests/App/Dashboard/SecurityEventsVolumeChart.test.tsx +321 -0
  98. package/Tests/App/Dashboard/SloOverviewHero.test.tsx +171 -36
  99. package/Tests/App/Dashboard/SloViewSideMenu.test.tsx +215 -0
  100. package/Tests/App/Dashboard/SloViewSideMenuCounts.test.tsx +40 -3
  101. package/Tests/App/PublicDashboard/DashboardVariableSelector.test.tsx +12 -4
  102. package/Tests/App/PublicDashboard/PublicDashboardWidgetListAuth.test.tsx +623 -0
  103. package/Tests/Models/OnCallCalendarFeedModels.test.ts +23 -1
  104. package/Tests/Server/API/AIChatRouteAuthorization.test.ts +138 -5
  105. package/Tests/Server/API/AIGenerationProjectAIToggle.test.ts +187 -0
  106. package/Tests/Server/API/AIInvestigationAvailabilityAuthorization.test.ts +51 -3
  107. package/Tests/Server/API/AIInvestigationEvidenceAPI.test.ts +55 -2
  108. package/Tests/Server/API/BaseAnalyticsAPIAggregateCache.test.ts +729 -0
  109. package/Tests/Server/API/BillingPayAsYouGoStatus.test.ts +93 -7
  110. package/Tests/Server/API/BillingPaymentMethodAPI.test.ts +36 -3
  111. package/Tests/Server/API/CommonAPIAuthGuard.test.ts +1003 -24
  112. package/Tests/Server/API/DashboardPublicRateLimit.test.ts +6 -3
  113. package/Tests/Server/API/ExpiredSessionAIRoutes.test.ts +708 -0
  114. package/Tests/Server/API/ExpiredSessionCustomRoutes.test.ts +928 -0
  115. package/Tests/Server/API/ExpiredSessionMonitorTemplate.test.ts +319 -0
  116. package/Tests/Server/API/ExpiredSessionOnCallDutyPolicy.test.ts +336 -0
  117. package/Tests/Server/API/ExpiredSessionRouteGuards.test.ts +820 -0
  118. package/Tests/Server/API/GlobalConfigLicense.test.ts +140 -0
  119. package/Tests/Server/API/NotificationChannelVerificationAPI.test.ts +115 -12
  120. package/Tests/Server/API/OnCallCalendarAPI.test.ts +375 -8
  121. package/Tests/Server/API/OnCallReadinessAPI.test.ts +175 -17
  122. package/Tests/Server/API/OnCallScheduleTimelineAPI.test.ts +1513 -0
  123. package/Tests/Server/API/OnCallSetupReminderAPI.test.ts +119 -7
  124. package/Tests/Server/API/ProjectScopedCustomRouteAuth.test.ts +111 -4
  125. package/Tests/Server/API/PublicRouteInvalidAccessToken.test.ts +615 -0
  126. package/Tests/Server/API/SecurityEventAttributesAPI.test.ts +89 -2
  127. package/Tests/Server/API/SessionReplayAPI.test.ts +121 -0
  128. package/Tests/Server/API/StatusPageMasterPasswordRateLimit.test.ts +4 -2
  129. package/Tests/Server/API/StatusPagePostmortemVisibility.test.ts +441 -0
  130. package/Tests/Server/API/StatusPageTestEmailReportAuth.test.ts +664 -0
  131. package/Tests/Server/API/TeamMemberRemoveUserFromProjectAPI.test.ts +7 -0
  132. package/Tests/Server/API/UserIncomingCallNumberApi.test.ts +6 -0
  133. package/Tests/Server/API/UserNotificationSettingAPI.test.ts +65 -4
  134. package/Tests/Server/API/UserProjectsAPI.test.ts +63 -3
  135. package/Tests/Server/API/UserTotpAuthAPI.test.ts +48 -2
  136. package/Tests/Server/API/UserWebAuthnAuthenticationOptionsRoute.test.ts +11 -2
  137. package/Tests/Server/API/UserWebAuthnBackupCodeMinting.test.ts +46 -3
  138. package/Tests/Server/API/UserWebAuthnPasskeyAPI.test.ts +18 -2
  139. package/Tests/Server/API/ZZVerifyChatsAuth.test.ts +24 -7
  140. package/Tests/Server/Middleware/ExpiredSessionUserMiddleware.test.ts +563 -0
  141. package/Tests/Server/Middleware/MasterAdminAuthorization.test.ts +299 -19
  142. package/Tests/Server/Middleware/PublicRouteUserMiddleware.test.ts +453 -0
  143. package/Tests/Server/Services/AIChatPrivacyPin.test.ts +24 -0
  144. package/Tests/Server/Services/ApiKeyPermissionSecurity.test.ts +2 -0
  145. package/Tests/Server/Services/ApiKeyPermissionService.test.ts +3 -3
  146. package/Tests/Server/Services/DatabaseServiceCreateSuppliedId.test.ts +147 -0
  147. package/Tests/Server/Services/DatabaseServiceLoginBeforeHooks.test.ts +1078 -0
  148. package/Tests/Server/Services/DatabaseServiceTenantRelationGuard.test.ts +259 -0
  149. package/Tests/Server/Services/DatabaseServiceWriteOperatorValues.test.ts +147 -0
  150. package/Tests/Server/Services/MonitorPayAsYouGoBilling.test.ts +115 -1
  151. package/Tests/Server/Services/OnCallChildCreateAuthorizationPostgres.test.ts +711 -0
  152. package/Tests/Server/Services/OnCallDutyPolicyChildService.test.ts +733 -0
  153. package/Tests/Server/Services/PayAsYouGoBillingService.test.ts +190 -140
  154. package/Tests/Server/Services/PayAsYouGoStripeRateLimitBudget.test.ts +4 -9
  155. package/Tests/Server/Services/PermissionBlockDeletion.test.ts +780 -0
  156. package/Tests/Server/Services/PermissionBlockDeletionPostgres.test.ts +628 -0
  157. package/Tests/Server/Services/ProjectServiceCreateSubscriptionStarted.test.ts +77 -1
  158. package/Tests/Server/Services/RumSessionPinCreatePermission.test.ts +715 -0
  159. package/Tests/Server/Services/TeamMemberMultiTenantReadPostgres.test.ts +394 -0
  160. package/Tests/Server/Services/TeamPrivilegeEscalation.test.ts +6 -0
  161. package/Tests/Server/Services/TelemetryPayAsYouGoBilling.test.ts +131 -0
  162. package/Tests/Server/Services/UserNotificationRuleAdminGuards.test.ts +13 -2
  163. package/Tests/Server/Types/Database/Permissions/ModelPermissionAnonymousRefusal.test.ts +518 -0
  164. package/Tests/Server/Types/Database/Permissions/MultiTenantPermissions.test.ts +350 -0
  165. package/Tests/Server/Types/Database/Permissions/OnCallCalendarFeedPermissions.test.ts +282 -25
  166. package/Tests/Server/Types/Database/Permissions/TableLevelBlockPermission.test.ts +459 -0
  167. package/Tests/Server/Utils/AI/AIRunPrivacyFilter.test.ts +101 -9
  168. package/Tests/Server/Utils/AI/ChatAgentHelpers.test.ts +88 -4
  169. package/Tests/Server/Utils/AI/Toolbox/ExceptionTools.test.ts +459 -0
  170. package/Tests/Server/Utils/AI/Toolbox/LogTools.test.ts +794 -0
  171. package/Tests/Server/Utils/AI/Toolbox/RecentChangesTools.test.ts +574 -0
  172. package/Tests/Server/Utils/AI/Toolbox/SecurityEventTools.test.ts +596 -0
  173. package/Tests/Server/Utils/CaptchaRequestAndLogging.test.ts +395 -0
  174. package/Tests/Server/Utils/MasterAdminPageAccess.test.ts +251 -0
  175. package/Tests/Server/Utils/Monitor/MonitorActionTimestamps.test.ts +616 -0
  176. package/Tests/Server/Utils/Realtime.test.ts +502 -0
  177. package/Tests/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsConnectorSeverity.test.ts +216 -0
  178. package/Tests/Server/Utils/SecurityEvent/DetectionRuleEvaluator.test.ts +142 -0
  179. package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsSeverityRepair.test.ts +140 -0
  180. package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsSeverityRepairClickhouseIntegration.test.ts +542 -0
  181. package/Tests/Server/Utils/Telemetry/ChangeEventRow.test.ts +743 -0
  182. package/Tests/Server/Utils/Telemetry/RuntimeMetrics.test.ts +465 -0
  183. package/Tests/Server/Utils/Workspace/MicrosoftTeams/Messages/Alert.test.ts +202 -0
  184. package/Tests/Server/Utils/Workspace/MicrosoftTeams/Messages/Incident.test.ts +194 -0
  185. package/Tests/Server/Utils/Workspace/MicrosoftTeams/Messages/ScheduledMaintenance.test.ts +231 -0
  186. package/Tests/Server/Utils/Workspace/Slack/Messages/Alert.test.ts +194 -0
  187. package/Tests/Server/Utils/Workspace/Slack/Messages/AlertEpisode.test.ts +194 -0
  188. package/Tests/Server/Utils/Workspace/Slack/Messages/Incident.test.ts +194 -0
  189. package/Tests/Server/Utils/Workspace/Slack/Messages/IncidentEpisode.test.ts +194 -0
  190. package/Tests/Server/Utils/Workspace/Slack/Messages/ScheduledMaintenance.test.ts +247 -0
  191. package/Tests/Types/AI/AIInsightEvidence.test.ts +206 -0
  192. package/Tests/Types/BaseDatabase/DatabaseCommonInteractionPropsUtilAnonymous.test.ts +144 -0
  193. package/Tests/Types/Call/CallProvider.test.ts +528 -0
  194. package/Tests/Types/Kubernetes/KubernetesCostIngest.test.ts +236 -0
  195. package/Tests/Types/OnCallDutyPolicy/ScheduleTimeline.test.ts +736 -0
  196. package/Tests/Types/OnCallDutyPolicy/ScheduleTimelineLayout.test.ts +996 -0
  197. package/Tests/Types/SecurityEvent/SigmaRule.test.ts +142 -0
  198. package/Tests/Types/Workflow/Components/JSON.test.ts +182 -0
  199. package/Tests/UI/Components/BasicFormDropdownNormalization.test.tsx +116 -1
  200. package/Tests/UI/Components/Dropdown/DropdownAsyncOptions.test.tsx +81 -0
  201. package/Tests/UI/Components/EditionLabelLicenseRefresh.test.tsx +89 -1
  202. package/Tests/UI/Components/EventAttachmentList.test.tsx +174 -0
  203. package/Tests/UI/Components/Forms/BasicFormBurnRateTemplateDefaults.test.tsx +395 -0
  204. package/Tests/UI/Components/Forms/BasicFormCollapsibleSections.test.tsx +286 -0
  205. package/Tests/UI/Components/Forms/FormSummary.test.tsx +128 -0
  206. package/Tests/UI/Components/ModelTable/BaseModelTableQueryChange.test.tsx +365 -0
  207. package/Tests/UI/Components/OpenAuthenticatedUrl.test.ts +358 -0
  208. package/Tests/UI/Components/SessionAwareImage.test.tsx +496 -0
  209. package/Tests/UI/Components/TelemetryHistogramZeroBuckets.test.tsx +190 -0
  210. package/Tests/UI/Components/TooltipInteractive.test.tsx +97 -0
  211. package/Tests/UI/MicrosoftTeams/MicrosoftTeamsChatsCardInstallGuidance.test.tsx +1 -1
  212. package/Tests/UI/Monitor/EvaluationLogListTimestamps.test.tsx +367 -0
  213. package/Tests/UI/Utils/API/BaseAPIRefreshSession.test.ts +1087 -0
  214. package/Tests/UI/Utils/API/DashboardHost.ts +12 -0
  215. package/Tests/UI/Utils/API/FakeAxiosServer.ts +183 -0
  216. package/Tests/UI/Utils/Breadcrumb/fixtures/RealBreadcrumbTrails.ts +10 -0
  217. package/Tests/UI/Utils/Breadcrumb/fixtures/RealRoutePatterns.ts +2 -0
  218. package/Tests/UI/Utils/Cookie.test.ts +440 -0
  219. package/Tests/UI/Utils/ModelAPIRequestClient.test.ts +278 -0
  220. package/Tests/UI/Utils/Navigation.test.ts +33 -0
  221. package/Tests/UI/Utils/PricingPlan.test.ts +295 -0
  222. package/Tests/UI/Utils/Realtime.test.ts +759 -0
  223. package/Tests/UI/Utils/Telemetry/Telemetry.test.ts +500 -0
  224. package/Tests/Utils/APIInstanceDispatch.test.ts +311 -0
  225. package/Tests/Utils/SecurityEvent/GoogleSecOpsAlertNormalizerSeverity.test.ts +565 -0
  226. package/Types/BaseDatabase/DatabaseCommonInteractionPropsUtil.ts +40 -0
  227. package/Types/Monitor/MonitorEvaluationSummary.ts +3 -0
  228. package/Types/OnCallDutyPolicy/ScheduleTimeline.ts +507 -0
  229. package/Types/OnCallDutyPolicy/ScheduleTimelineLayout.ts +589 -0
  230. package/Types/Realtime/EventName.ts +11 -0
  231. package/Types/SecurityEvent/DetectionFindingConstants.ts +14 -0
  232. package/Types/SecurityEvent/OcsfSeverity.ts +31 -26
  233. package/Types/SecurityEvent/SigmaRule.ts +51 -0
  234. package/Types/SecurityEvent/ThreatIntelConstants.ts +18 -0
  235. package/UI/Components/AttachmentList/EventAttachmentList.tsx +30 -2
  236. package/UI/Components/Dashboard/DashboardVariableControl.tsx +12 -2
  237. package/UI/Components/Dropdown/Dropdown.tsx +6 -1
  238. package/UI/Components/EditionLabel/EditionLabel.tsx +12 -0
  239. package/UI/Components/EventItem/EventItem.tsx +12 -1
  240. package/UI/Components/Forms/BasicForm.tsx +151 -126
  241. package/UI/Components/Forms/CollapsibleFormSection.tsx +63 -0
  242. package/UI/Components/Forms/Fields/FormField.tsx +10 -4
  243. package/UI/Components/Forms/FormSummary.tsx +7 -0
  244. package/UI/Components/Forms/Types/Field.ts +10 -0
  245. package/UI/Components/Markdown.tsx/MarkdownViewer.tsx +2 -1
  246. package/UI/Components/Markdown.tsx/SessionAwareImage.tsx +122 -0
  247. package/UI/Components/ModelTable/BaseModelTable.tsx +34 -5
  248. package/UI/Components/ModelTable/TableView.tsx +1 -1
  249. package/UI/Components/TelemetryViewer/components/TelemetryHistogram.tsx +8 -1
  250. package/UI/Components/Tooltip/Tooltip.tsx +8 -1
  251. package/UI/Utils/API/API.ts +173 -12
  252. package/UI/Utils/API/RequestOptions.ts +11 -0
  253. package/UI/Utils/AnalyticsModelAPI/AnalyticsModelAPI.ts +31 -7
  254. package/UI/Utils/ModelAPI/ModelAPI.ts +30 -9
  255. package/UI/Utils/Navigation.ts +9 -0
  256. package/UI/Utils/OpenAuthenticatedUrl.ts +154 -0
  257. package/UI/Utils/Realtime.ts +176 -30
  258. package/Utils/API.ts +14 -5
  259. package/Utils/SecurityEvent/GoogleSecOpsAlertNormalizer.ts +157 -7
  260. package/Utils/SecurityEvent/Sigma/SigmaRuleParser.ts +9 -17
  261. package/Utils/Slo/SloBurnRateTemplate.ts +2 -2
  262. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyScheduleCalendarFeed.js +1 -1
  263. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyScheduleCalendarFeed.js.map +1 -1
  264. package/build/dist/Models/DatabaseModels/ProjectOnCallCalendarFeed.js +1 -1
  265. package/build/dist/Models/DatabaseModels/ProjectOnCallCalendarFeed.js.map +1 -1
  266. package/build/dist/Models/DatabaseModels/UserOnCallCalendarFeed.js +1 -1
  267. package/build/dist/Models/DatabaseModels/UserOnCallCalendarFeed.js.map +1 -1
  268. package/build/dist/Server/API/AIBillingAPI.js +1 -1
  269. package/build/dist/Server/API/AIBillingAPI.js.map +1 -1
  270. package/build/dist/Server/API/AIInsightAPI.js +1 -4
  271. package/build/dist/Server/API/AIInsightAPI.js.map +1 -1
  272. package/build/dist/Server/API/AIInvestigationAPI.js +1 -4
  273. package/build/dist/Server/API/AIInvestigationAPI.js.map +1 -1
  274. package/build/dist/Server/API/AIReadinessAPI.js +1 -3
  275. package/build/dist/Server/API/AIReadinessAPI.js.map +1 -1
  276. package/build/dist/Server/API/AlertAPI.js +1 -1
  277. package/build/dist/Server/API/AlertAPI.js.map +1 -1
  278. package/build/dist/Server/API/AutoRemediationAPI.js +1 -4
  279. package/build/dist/Server/API/AutoRemediationAPI.js.map +1 -1
  280. package/build/dist/Server/API/BaseAPI.js +12 -0
  281. package/build/dist/Server/API/BaseAPI.js.map +1 -1
  282. package/build/dist/Server/API/BaseAnalyticsAPI.js +55 -10
  283. package/build/dist/Server/API/BaseAnalyticsAPI.js.map +1 -1
  284. package/build/dist/Server/API/BillingAPI.js +2 -2
  285. package/build/dist/Server/API/BillingAPI.js.map +1 -1
  286. package/build/dist/Server/API/BillingInvoiceAPI.js +1 -1
  287. package/build/dist/Server/API/BillingInvoiceAPI.js.map +1 -1
  288. package/build/dist/Server/API/BillingPaymentMethodAPI.js +2 -2
  289. package/build/dist/Server/API/BillingPaymentMethodAPI.js.map +1 -1
  290. package/build/dist/Server/API/CodeFixRunAPI.js +1 -3
  291. package/build/dist/Server/API/CodeFixRunAPI.js.map +1 -1
  292. package/build/dist/Server/API/CommonAPI.js +50 -5
  293. package/build/dist/Server/API/CommonAPI.js.map +1 -1
  294. package/build/dist/Server/API/DashboardAPI.js +12 -12
  295. package/build/dist/Server/API/DashboardAPI.js.map +1 -1
  296. package/build/dist/Server/API/GlobalConfigAPI.js +12 -0
  297. package/build/dist/Server/API/GlobalConfigAPI.js.map +1 -1
  298. package/build/dist/Server/API/IncidentAPI.js +2 -2
  299. package/build/dist/Server/API/IncidentAPI.js.map +1 -1
  300. package/build/dist/Server/API/IncidentEpisodeAPI.js +1 -1
  301. package/build/dist/Server/API/IncidentEpisodeAPI.js.map +1 -1
  302. package/build/dist/Server/API/NotificationAPI.js +1 -1
  303. package/build/dist/Server/API/NotificationAPI.js.map +1 -1
  304. package/build/dist/Server/API/OnCallCalendarAPI.js +1 -4
  305. package/build/dist/Server/API/OnCallCalendarAPI.js.map +1 -1
  306. package/build/dist/Server/API/OnCallDutyPolicyAPI.js +6 -0
  307. package/build/dist/Server/API/OnCallDutyPolicyAPI.js.map +1 -1
  308. package/build/dist/Server/API/OnCallReadinessAPI.js +4 -1
  309. package/build/dist/Server/API/OnCallReadinessAPI.js.map +1 -1
  310. package/build/dist/Server/API/OnCallScheduleTimelineAPI.js +494 -0
  311. package/build/dist/Server/API/OnCallScheduleTimelineAPI.js.map +1 -0
  312. package/build/dist/Server/API/ProjectAPI.js +1 -1
  313. package/build/dist/Server/API/ProjectAPI.js.map +1 -1
  314. package/build/dist/Server/API/ScheduledMaintenanceAPI.js +1 -1
  315. package/build/dist/Server/API/ScheduledMaintenanceAPI.js.map +1 -1
  316. package/build/dist/Server/API/StatusPageAPI.js +125 -33
  317. package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
  318. package/build/dist/Server/API/TeamMemberAPI.js +3 -3
  319. package/build/dist/Server/API/TeamMemberAPI.js.map +1 -1
  320. package/build/dist/Server/API/UserCallAPI.js +2 -2
  321. package/build/dist/Server/API/UserCallAPI.js.map +1 -1
  322. package/build/dist/Server/API/UserEmailAPI.js +2 -2
  323. package/build/dist/Server/API/UserEmailAPI.js.map +1 -1
  324. package/build/dist/Server/API/UserIncomingCallNumberAPI.js +2 -2
  325. package/build/dist/Server/API/UserIncomingCallNumberAPI.js.map +1 -1
  326. package/build/dist/Server/API/UserMicrosoftTeamsAPI.js +1 -1
  327. package/build/dist/Server/API/UserMicrosoftTeamsAPI.js.map +1 -1
  328. package/build/dist/Server/API/UserSlackAPI.js +1 -1
  329. package/build/dist/Server/API/UserSlackAPI.js.map +1 -1
  330. package/build/dist/Server/API/UserSmsAPI.js +2 -2
  331. package/build/dist/Server/API/UserSmsAPI.js.map +1 -1
  332. package/build/dist/Server/API/UserTotpAuthAPI.js +1 -1
  333. package/build/dist/Server/API/UserTotpAuthAPI.js.map +1 -1
  334. package/build/dist/Server/API/UserWebAuthnAPI.js +2 -2
  335. package/build/dist/Server/API/UserWebAuthnAPI.js.map +1 -1
  336. package/build/dist/Server/API/UserWebhookAPI.js +1 -1
  337. package/build/dist/Server/API/UserWebhookAPI.js.map +1 -1
  338. package/build/dist/Server/API/UserWhatsAppAPI.js +2 -2
  339. package/build/dist/Server/API/UserWhatsAppAPI.js.map +1 -1
  340. package/build/dist/Server/Middleware/MasterAdminAuthorization.js +11 -2
  341. package/build/dist/Server/Middleware/MasterAdminAuthorization.js.map +1 -1
  342. package/build/dist/Server/Middleware/UserAuthorization.js +64 -4
  343. package/build/dist/Server/Middleware/UserAuthorization.js.map +1 -1
  344. package/build/dist/Server/Services/ApiKeyPermissionService.js +80 -4
  345. package/build/dist/Server/Services/ApiKeyPermissionService.js.map +1 -1
  346. package/build/dist/Server/Services/DatabaseService.js +171 -0
  347. package/build/dist/Server/Services/DatabaseService.js.map +1 -1
  348. package/build/dist/Server/Services/DetectionRuleService.js +4 -4
  349. package/build/dist/Server/Services/DetectionRuleService.js.map +1 -1
  350. package/build/dist/Server/Services/OnCallDutyPolicyChildService.js +170 -0
  351. package/build/dist/Server/Services/OnCallDutyPolicyChildService.js.map +1 -0
  352. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js +2 -2
  353. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js.map +1 -1
  354. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleService.js +2 -2
  355. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleService.js.map +1 -1
  356. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleTeamService.js +2 -2
  357. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleTeamService.js.map +1 -1
  358. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleUserService.js +2 -2
  359. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleUserService.js.map +1 -1
  360. package/build/dist/Server/Services/PayAsYouGoBillingService.js +20 -27
  361. package/build/dist/Server/Services/PayAsYouGoBillingService.js.map +1 -1
  362. package/build/dist/Server/Services/ProjectService.js +17 -0
  363. package/build/dist/Server/Services/ProjectService.js.map +1 -1
  364. package/build/dist/Server/Services/RumSessionPinService.js +180 -16
  365. package/build/dist/Server/Services/RumSessionPinService.js.map +1 -1
  366. package/build/dist/Server/Services/TeamPermissionService.js +89 -27
  367. package/build/dist/Server/Services/TeamPermissionService.js.map +1 -1
  368. package/build/dist/Server/Services/ThreatIntelFeedService.js +5 -4
  369. package/build/dist/Server/Services/ThreatIntelFeedService.js.map +1 -1
  370. package/build/dist/Server/Types/Database/Permissions/BasePermission.js +9 -6
  371. package/build/dist/Server/Types/Database/Permissions/BasePermission.js.map +1 -1
  372. package/build/dist/Server/Types/Database/Permissions/Index.js +60 -6
  373. package/build/dist/Server/Types/Database/Permissions/Index.js.map +1 -1
  374. package/build/dist/Server/Types/Database/Permissions/TablePermission.js +14 -13
  375. package/build/dist/Server/Types/Database/Permissions/TablePermission.js.map +1 -1
  376. package/build/dist/Server/Utils/AI/AIChatPrivacyFilter.js +7 -0
  377. package/build/dist/Server/Utils/AI/AIChatPrivacyFilter.js.map +1 -1
  378. package/build/dist/Server/Utils/AI/AIRunPrivacyFilter.js +7 -0
  379. package/build/dist/Server/Utils/AI/AIRunPrivacyFilter.js.map +1 -1
  380. package/build/dist/Server/Utils/MasterAdminPageAccess.js +39 -0
  381. package/build/dist/Server/Utils/MasterAdminPageAccess.js.map +1 -0
  382. package/build/dist/Server/Utils/Monitor/MonitorAlert.js +3 -1
  383. package/build/dist/Server/Utils/Monitor/MonitorAlert.js.map +1 -1
  384. package/build/dist/Server/Utils/Monitor/MonitorIncident.js +3 -1
  385. package/build/dist/Server/Utils/Monitor/MonitorIncident.js.map +1 -1
  386. package/build/dist/Server/Utils/Realtime.js +126 -37
  387. package/build/dist/Server/Utils/Realtime.js.map +1 -1
  388. package/build/dist/Server/Utils/SecurityEvent/DetectionRuleEvaluator.js +7 -25
  389. package/build/dist/Server/Utils/SecurityEvent/DetectionRuleEvaluator.js.map +1 -1
  390. package/build/dist/Server/Utils/SecurityEvent/GoogleSecOpsSeverityRepair.js +127 -0
  391. package/build/dist/Server/Utils/SecurityEvent/GoogleSecOpsSeverityRepair.js.map +1 -0
  392. package/build/dist/Server/Utils/SecurityEvent/Sigma/SigmaClickhouseCompiler.js +1 -1
  393. package/build/dist/Server/Utils/SecurityEvent/Sigma/SigmaClickhouseCompiler.js.map +1 -1
  394. package/build/dist/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelFeedPoller.js +3 -2
  395. package/build/dist/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelFeedPoller.js.map +1 -1
  396. package/build/dist/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelMatcher.js +4 -8
  397. package/build/dist/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelMatcher.js.map +1 -1
  398. package/build/dist/Types/BaseDatabase/DatabaseCommonInteractionPropsUtil.js +31 -1
  399. package/build/dist/Types/BaseDatabase/DatabaseCommonInteractionPropsUtil.js.map +1 -1
  400. package/build/dist/Types/OnCallDutyPolicy/ScheduleTimeline.js +321 -0
  401. package/build/dist/Types/OnCallDutyPolicy/ScheduleTimeline.js.map +1 -0
  402. package/build/dist/Types/OnCallDutyPolicy/ScheduleTimelineLayout.js +372 -0
  403. package/build/dist/Types/OnCallDutyPolicy/ScheduleTimelineLayout.js.map +1 -0
  404. package/build/dist/Types/Realtime/EventName.js +10 -0
  405. package/build/dist/Types/Realtime/EventName.js.map +1 -1
  406. package/build/dist/Types/SecurityEvent/DetectionFindingConstants.js +11 -0
  407. package/build/dist/Types/SecurityEvent/DetectionFindingConstants.js.map +1 -1
  408. package/build/dist/Types/SecurityEvent/OcsfSeverity.js +30 -25
  409. package/build/dist/Types/SecurityEvent/OcsfSeverity.js.map +1 -1
  410. package/build/dist/Types/SecurityEvent/SigmaRule.js +47 -0
  411. package/build/dist/Types/SecurityEvent/SigmaRule.js.map +1 -1
  412. package/build/dist/Types/SecurityEvent/ThreatIntelConstants.js +14 -0
  413. package/build/dist/Types/SecurityEvent/ThreatIntelConstants.js.map +1 -1
  414. package/build/dist/UI/Components/AttachmentList/EventAttachmentList.js +9 -4
  415. package/build/dist/UI/Components/AttachmentList/EventAttachmentList.js.map +1 -1
  416. package/build/dist/UI/Components/Dashboard/DashboardVariableControl.js +10 -2
  417. package/build/dist/UI/Components/Dashboard/DashboardVariableControl.js.map +1 -1
  418. package/build/dist/UI/Components/Dropdown/Dropdown.js +5 -1
  419. package/build/dist/UI/Components/Dropdown/Dropdown.js.map +1 -1
  420. package/build/dist/UI/Components/EditionLabel/EditionLabel.js +11 -0
  421. package/build/dist/UI/Components/EditionLabel/EditionLabel.js.map +1 -1
  422. package/build/dist/UI/Components/EventItem/EventItem.js +2 -2
  423. package/build/dist/UI/Components/EventItem/EventItem.js.map +1 -1
  424. package/build/dist/UI/Components/Forms/BasicForm.js +70 -64
  425. package/build/dist/UI/Components/Forms/BasicForm.js.map +1 -1
  426. package/build/dist/UI/Components/Forms/CollapsibleFormSection.js +27 -0
  427. package/build/dist/UI/Components/Forms/CollapsibleFormSection.js.map +1 -0
  428. package/build/dist/UI/Components/Forms/Fields/FormField.js +10 -7
  429. package/build/dist/UI/Components/Forms/Fields/FormField.js.map +1 -1
  430. package/build/dist/UI/Components/Forms/FormSummary.js +7 -0
  431. package/build/dist/UI/Components/Forms/FormSummary.js.map +1 -1
  432. package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js +2 -1
  433. package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js.map +1 -1
  434. package/build/dist/UI/Components/Markdown.tsx/SessionAwareImage.js +84 -0
  435. package/build/dist/UI/Components/Markdown.tsx/SessionAwareImage.js.map +1 -0
  436. package/build/dist/UI/Components/ModelTable/BaseModelTable.js +14 -1
  437. package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
  438. package/build/dist/UI/Components/ModelTable/TableView.js +1 -1
  439. package/build/dist/UI/Components/ModelTable/TableView.js.map +1 -1
  440. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryHistogram.js +8 -1
  441. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryHistogram.js.map +1 -1
  442. package/build/dist/UI/Components/Tooltip/Tooltip.js +2 -1
  443. package/build/dist/UI/Components/Tooltip/Tooltip.js.map +1 -1
  444. package/build/dist/UI/Utils/API/API.js +143 -19
  445. package/build/dist/UI/Utils/API/API.js.map +1 -1
  446. package/build/dist/UI/Utils/AnalyticsModelAPI/AnalyticsModelAPI.js +21 -7
  447. package/build/dist/UI/Utils/AnalyticsModelAPI/AnalyticsModelAPI.js.map +1 -1
  448. package/build/dist/UI/Utils/ModelAPI/ModelAPI.js +26 -9
  449. package/build/dist/UI/Utils/ModelAPI/ModelAPI.js.map +1 -1
  450. package/build/dist/UI/Utils/Navigation.js +8 -0
  451. package/build/dist/UI/Utils/Navigation.js.map +1 -1
  452. package/build/dist/UI/Utils/OpenAuthenticatedUrl.js +92 -0
  453. package/build/dist/UI/Utils/OpenAuthenticatedUrl.js.map +1 -0
  454. package/build/dist/UI/Utils/Realtime.js +120 -15
  455. package/build/dist/UI/Utils/Realtime.js.map +1 -1
  456. package/build/dist/Utils/API.js +13 -5
  457. package/build/dist/Utils/API.js.map +1 -1
  458. package/build/dist/Utils/SecurityEvent/GoogleSecOpsAlertNormalizer.js +123 -6
  459. package/build/dist/Utils/SecurityEvent/GoogleSecOpsAlertNormalizer.js.map +1 -1
  460. package/build/dist/Utils/SecurityEvent/Sigma/SigmaRuleParser.js +4 -18
  461. package/build/dist/Utils/SecurityEvent/Sigma/SigmaRuleParser.js.map +1 -1
  462. package/build/dist/Utils/Slo/SloBurnRateTemplate.js +2 -2
  463. package/package.json +1 -1
@@ -0,0 +1,761 @@
1
+ /** @timezone UTC */
2
+
3
+ import "@testing-library/jest-dom";
4
+ import {
5
+ afterEach,
6
+ beforeEach,
7
+ describe,
8
+ expect,
9
+ jest,
10
+ test,
11
+ } from "@jest/globals";
12
+ import {
13
+ act,
14
+ cleanup,
15
+ configure,
16
+ fireEvent,
17
+ render,
18
+ screen,
19
+ waitFor,
20
+ within,
21
+ } from "@testing-library/react";
22
+ import React, { ReactElement } from "react";
23
+ import { MemoryRouter } from "react-router-dom";
24
+ import { MockFunction } from "../../MockType";
25
+
26
+ configure({ asyncUtilTimeout: 15000 });
27
+
28
+ /*
29
+ * The Security Events page: a volume chart stacked by severity over the page's
30
+ * time window, above the events table. What is pinned here is the wiring that
31
+ * only shows once the pieces are together - the window the range picker sets
32
+ * reaching both the table and the chart, the chart counting exactly what the
33
+ * table reports it lists, drag-to-zoom and Refresh moving both, the URL
34
+ * carrying the window, and the empty table telling "nothing in this window"
35
+ * apart from "nothing ever".
36
+ *
37
+ * The data layer is stubbed (AnalyticsModelAPI), as is the table itself: its
38
+ * half of the contract - reporting the query it lists with - is pinned against
39
+ * a real BaseModelTable in BaseModelTableQueryChange.test.tsx, and the stub
40
+ * below honours it the same way (once on mount, again when the query moves).
41
+ */
42
+
43
+ interface CapturedTableProps {
44
+ id?: string;
45
+ query: Record<string, unknown>;
46
+ onQueryChange?: (query: Record<string, unknown>) => void;
47
+ refreshToggle?: string;
48
+ noItemsMessage?: ReactElement;
49
+ showRefreshButton?: boolean;
50
+ filters: Array<{ field: Record<string, boolean>; title: string }>;
51
+ }
52
+
53
+ let tableProps: CapturedTableProps | null = null;
54
+
55
+ jest.mock("../../../UI/Components/ModelTable/AnalyticsModelTable", () => {
56
+ const react: typeof React = jest.requireActual("react") as typeof React;
57
+
58
+ return {
59
+ __esModule: true,
60
+ default: (props: CapturedTableProps): ReactElement => {
61
+ tableProps = props;
62
+ const queryKey: string = JSON.stringify(props.query);
63
+
64
+ react.useEffect(() => {
65
+ props.onQueryChange?.(props.query);
66
+ }, [queryKey]);
67
+
68
+ return react.createElement(
69
+ "div",
70
+ { "data-testid": "security-events-analytics-table" },
71
+ props.noItemsMessage || null,
72
+ );
73
+ },
74
+ };
75
+ });
76
+
77
+ interface CapturedPickerProps {
78
+ value: { range: string; startAndEndDate?: unknown };
79
+ onChange: (value: unknown) => void;
80
+ }
81
+
82
+ let pickerProps: CapturedPickerProps | null = null;
83
+
84
+ jest.mock(
85
+ "../../../UI/Components/TelemetryViewer/components/TelemetryTimeRangePicker",
86
+ () => {
87
+ const react: typeof React = jest.requireActual("react") as typeof React;
88
+
89
+ return {
90
+ __esModule: true,
91
+ default: (props: CapturedPickerProps): ReactElement => {
92
+ pickerProps = props;
93
+ return react.createElement(
94
+ "div",
95
+ { "data-testid": "time-range-picker" },
96
+ props.value.range,
97
+ );
98
+ },
99
+ };
100
+ },
101
+ );
102
+
103
+ // See TelemetryHistogramDragTooltip.test.tsx: one div per bucket, so a drag can be driven.
104
+ jest.mock("recharts", () => {
105
+ const react: typeof React = jest.requireActual("react") as typeof React;
106
+
107
+ interface StubRow {
108
+ time: string;
109
+ }
110
+
111
+ interface StubChartProps {
112
+ data: Array<StubRow>;
113
+ children?: React.ReactNode;
114
+ onMouseDown?: (state: { activeLabel: string }) => void;
115
+ onMouseMove?: (state: { activeLabel: string }) => void;
116
+ onMouseUp?: (state: { activeLabel: string }) => void;
117
+ }
118
+
119
+ return {
120
+ __esModule: true,
121
+ ResponsiveContainer: (props: { children: React.ReactNode }) => {
122
+ return react.createElement("div", null, props.children);
123
+ },
124
+ BarChart: (props: StubChartProps) => {
125
+ return react.createElement(
126
+ "div",
127
+ { "data-testid": "bar-chart" },
128
+ props.data.map((row: StubRow) => {
129
+ return react.createElement("div", {
130
+ key: row.time,
131
+ "data-testid": `bucket-${row.time}`,
132
+ onMouseDown: () => {
133
+ props.onMouseDown?.({ activeLabel: row.time });
134
+ },
135
+ onMouseMove: () => {
136
+ props.onMouseMove?.({ activeLabel: row.time });
137
+ },
138
+ onMouseUp: () => {
139
+ props.onMouseUp?.({ activeLabel: row.time });
140
+ },
141
+ });
142
+ }),
143
+ props.children,
144
+ );
145
+ },
146
+ Bar: () => {
147
+ return null;
148
+ },
149
+ XAxis: () => {
150
+ return null;
151
+ },
152
+ YAxis: () => {
153
+ return null;
154
+ },
155
+ Tooltip: () => {
156
+ return null;
157
+ },
158
+ ReferenceArea: () => {
159
+ return null;
160
+ },
161
+ };
162
+ });
163
+
164
+ import SecurityEventsExplorer, {
165
+ SECURITY_EVENTS_REFRESH_TEST_ID,
166
+ } from "../../../../App/FeatureSet/Dashboard/src/Components/SecurityEvents/SecurityEventsExplorer";
167
+ import SecurityEventsEmptyState from "../../../../App/FeatureSet/Dashboard/src/Components/SecurityEvents/SecurityEventsEmptyState";
168
+ import SecurityEventsNoResults, {
169
+ SECURITY_EVENTS_NO_RESULTS_ID,
170
+ } from "../../../../App/FeatureSet/Dashboard/src/Components/SecurityEvents/SecurityEventsNoResults";
171
+ import { SECURITY_EVENTS_VOLUME_TEST_ID } from "../../../../App/FeatureSet/Dashboard/src/Components/SecurityEvents/SecurityEventsVolumeChart";
172
+ import AnalyticsModelAPI from "../../../UI/Utils/AnalyticsModelAPI/AnalyticsModelAPI";
173
+ import ProjectUtil from "../../../UI/Utils/Project";
174
+ import TableFilterUrlState from "../../../UI/Utils/TableFilterUrlState";
175
+ import AggregateBy from "../../../Types/BaseDatabase/AggregateBy";
176
+ import AggregatedModel from "../../../Types/BaseDatabase/AggregatedModel";
177
+ import AggregatedResult from "../../../Types/BaseDatabase/AggregatedResult";
178
+ import InBetween from "../../../Types/BaseDatabase/InBetween";
179
+ import Includes from "../../../Types/BaseDatabase/Includes";
180
+ import ListResult from "../../../Types/BaseDatabase/ListResult";
181
+ import OneUptimeDate from "../../../Types/Date";
182
+ import ObjectID from "../../../Types/ObjectID";
183
+ import OcsfSeverity from "../../../Types/SecurityEvent/OcsfSeverity";
184
+ import SortOrder from "../../../Types/BaseDatabase/SortOrder";
185
+ import TimeRange from "../../../Types/Time/TimeRange";
186
+ import SecurityEvent from "../../../Models/AnalyticsModels/SecurityEvent";
187
+
188
+ const PROJECT_ID: ObjectID = new ObjectID(
189
+ "11111111-1111-4111-8111-111111111111",
190
+ );
191
+
192
+ const NOW: Date = new Date("2026-09-18T12:00:00.000Z");
193
+ const MINUTE_MS: number = 60 * 1000;
194
+ const HOUR_MS: number = 60 * MINUTE_MS;
195
+ const DAY_MS: number = 24 * HOUR_MS;
196
+
197
+ let now: Date = NOW;
198
+
199
+ type AggregateCall = { aggregateBy: AggregateBy<SecurityEvent> };
200
+
201
+ /*
202
+ * aggregate and getList are generic statics, which spyOn's typing cannot
203
+ * express as a SpiedFunction of the method; the calls are read back untyped
204
+ * and cast where they are inspected.
205
+ */
206
+ let aggregateMock: MockFunction;
207
+ let getListMock: MockFunction;
208
+
209
+ function row(
210
+ timestamp: string,
211
+ severity: OcsfSeverity,
212
+ value: number,
213
+ ): AggregatedModel {
214
+ return {
215
+ timestamp: timestamp as unknown as Date,
216
+ value: value,
217
+ severityName: severity,
218
+ };
219
+ }
220
+
221
+ const SOME_EVENTS: Array<AggregatedModel> = [
222
+ row("2026-09-18T10:00:00.000Z", OcsfSeverity.High, 3),
223
+ row("2026-09-18T10:15:00.000Z", OcsfSeverity.Critical, 1),
224
+ row("2026-09-18T10:30:00.000Z", OcsfSeverity.Informational, 3),
225
+ ];
226
+
227
+ function resolvesWith(rows: Array<AggregatedModel>): void {
228
+ aggregateMock.mockImplementation(async (): Promise<AggregatedResult> => {
229
+ return { data: rows };
230
+ });
231
+ }
232
+
233
+ function aggregateCalls(): Array<AggregateBy<SecurityEvent>> {
234
+ return aggregateMock.mock.calls.map(
235
+ (call: Array<unknown>): AggregateBy<SecurityEvent> => {
236
+ return (call[0] as AggregateCall).aggregateBy;
237
+ },
238
+ );
239
+ }
240
+
241
+ function lastAggregate(): AggregateBy<SecurityEvent> {
242
+ const calls: Array<AggregateBy<SecurityEvent>> = aggregateCalls();
243
+ return calls[calls.length - 1]!;
244
+ }
245
+
246
+ function tableWindow(): { start: string; end: string } {
247
+ const time: InBetween<Date> = tableProps!.query["time"] as InBetween<Date>;
248
+ expect(time).toBeInstanceOf(InBetween);
249
+ return {
250
+ start: new Date(time.startValue).toISOString(),
251
+ end: new Date(time.endValue).toISOString(),
252
+ };
253
+ }
254
+
255
+ function urlParams(): URLSearchParams {
256
+ return new URLSearchParams(window.location.search);
257
+ }
258
+
259
+ function renderExplorer(): void {
260
+ render(
261
+ <MemoryRouter>
262
+ <SecurityEventsExplorer />
263
+ </MemoryRouter>,
264
+ );
265
+ }
266
+
267
+ async function waitForCounts(calls: number = 1): Promise<void> {
268
+ await waitFor(() => {
269
+ expect(aggregateMock).toHaveBeenCalledTimes(calls);
270
+ });
271
+ await waitFor(() => {
272
+ expect(
273
+ screen.getByTestId(SECURITY_EVENTS_VOLUME_TEST_ID),
274
+ ).not.toHaveAttribute("aria-busy", "true");
275
+ });
276
+ }
277
+
278
+ function totalText(): string {
279
+ return (
280
+ screen.getByTestId(`${SECURITY_EVENTS_VOLUME_TEST_ID}-total`).textContent ||
281
+ ""
282
+ );
283
+ }
284
+
285
+ beforeEach(() => {
286
+ tableProps = null;
287
+ pickerProps = null;
288
+ now = NOW;
289
+ window.history.replaceState(null, "", "/dashboard/project/security-events");
290
+ TableFilterUrlState.resetClaimedKeys();
291
+ jest.spyOn(ProjectUtil, "getCurrentProjectId").mockReturnValue(PROJECT_ID);
292
+ jest.spyOn(OneUptimeDate, "getCurrentDate").mockImplementation(() => {
293
+ return new Date(now.getTime());
294
+ });
295
+ aggregateMock = jest.spyOn(
296
+ AnalyticsModelAPI,
297
+ "aggregate",
298
+ ) as unknown as MockFunction;
299
+ getListMock = jest.spyOn(
300
+ AnalyticsModelAPI,
301
+ "getList",
302
+ ) as unknown as MockFunction;
303
+ resolvesWith(SOME_EVENTS);
304
+ getListMock.mockImplementation(async (): Promise<ListResult<never>> => {
305
+ return { data: [], count: 0, skip: 0, limit: 1 };
306
+ });
307
+ });
308
+
309
+ afterEach(() => {
310
+ cleanup();
311
+ jest.restoreAllMocks();
312
+ });
313
+
314
+ describe("SecurityEventsExplorer: the window", () => {
315
+ test("opens on the past day, scoped to the current project", async () => {
316
+ renderExplorer();
317
+ await waitForCounts();
318
+
319
+ expect(tableProps!.query["projectId"]).toBe(PROJECT_ID);
320
+ expect(tableWindow()).toEqual({
321
+ start: new Date(NOW.getTime() - DAY_MS).toISOString(),
322
+ end: NOW.toISOString(),
323
+ });
324
+ expect(pickerProps!.value).toEqual({ range: TimeRange.PAST_ONE_DAY });
325
+ });
326
+
327
+ test("puts the window in the URL, relative ranges without dates", async () => {
328
+ renderExplorer();
329
+ await waitForCounts();
330
+
331
+ expect(urlParams().get("range")).toBe(TimeRange.PAST_ONE_DAY);
332
+ expect(urlParams().get("start")).toBeNull();
333
+ expect(urlParams().get("end")).toBeNull();
334
+ });
335
+
336
+ test("opens on the window a link names", async () => {
337
+ window.history.replaceState(
338
+ null,
339
+ "",
340
+ "/dashboard/project/security-events?range=Custom&start=2026-09-10T00:00:00.000Z&end=2026-09-11T00:00:00.000Z",
341
+ );
342
+
343
+ renderExplorer();
344
+ await waitForCounts();
345
+
346
+ expect(tableWindow()).toEqual({
347
+ start: "2026-09-10T00:00:00.000Z",
348
+ end: "2026-09-11T00:00:00.000Z",
349
+ });
350
+ expect(pickerProps!.value.range).toBe(TimeRange.CUSTOM);
351
+ });
352
+
353
+ test("honours an older link that set the window as a table time filter", async () => {
354
+ const params: Record<string, string> =
355
+ TableFilterUrlState.getLinkQueryParams("security-events-table", {
356
+ filter: {
357
+ time: new InBetween<Date>(
358
+ new Date("2026-09-12T08:00:00.000Z"),
359
+ new Date("2026-09-12T09:00:00.000Z"),
360
+ ),
361
+ },
362
+ });
363
+ window.history.replaceState(
364
+ null,
365
+ "",
366
+ `/dashboard/project/security-events?security-events-table-filter=${params["security-events-table-filter"]}`,
367
+ );
368
+
369
+ renderExplorer();
370
+ await waitForCounts();
371
+
372
+ expect(tableWindow()).toEqual({
373
+ start: "2026-09-12T08:00:00.000Z",
374
+ end: "2026-09-12T09:00:00.000Z",
375
+ });
376
+ expect(urlParams().get("range")).toBe(TimeRange.CUSTOM);
377
+ expect(urlParams().get("start")).toBe("2026-09-12T08:00:00.000Z");
378
+ });
379
+
380
+ test("picking a range moves the table, the chart and the URL", async () => {
381
+ renderExplorer();
382
+ await waitForCounts();
383
+
384
+ act(() => {
385
+ pickerProps!.onChange({ range: TimeRange.PAST_ONE_WEEK });
386
+ });
387
+ await waitForCounts(2);
388
+
389
+ expect(tableWindow()).toEqual({
390
+ start: new Date(NOW.getTime() - 7 * DAY_MS).toISOString(),
391
+ end: NOW.toISOString(),
392
+ });
393
+ expect(new Date(lastAggregate().startTimestamp).toISOString()).toBe(
394
+ new Date(NOW.getTime() - 7 * DAY_MS).toISOString(),
395
+ );
396
+ expect(urlParams().get("range")).toBe(TimeRange.PAST_ONE_WEEK);
397
+ });
398
+
399
+ test("a re-render does not move a relative window on its own", async () => {
400
+ renderExplorer();
401
+ await waitForCounts();
402
+
403
+ const before: { start: string; end: string } = tableWindow();
404
+ now = new Date(NOW.getTime() + 10 * MINUTE_MS);
405
+
406
+ // Anything that re-renders the page: here, the table reporting a filter.
407
+ act(() => {
408
+ tableProps!.onQueryChange!({
409
+ ...tableProps!.query,
410
+ severityName: new Includes([OcsfSeverity.High]),
411
+ });
412
+ });
413
+ await waitForCounts(2);
414
+
415
+ expect(tableWindow()).toEqual(before);
416
+ });
417
+ });
418
+
419
+ describe("SecurityEventsExplorer: the chart", () => {
420
+ test("counts exactly the query the table reports it lists", async () => {
421
+ renderExplorer();
422
+ await waitForCounts();
423
+
424
+ expect(lastAggregate().query).toEqual(tableProps!.query);
425
+ expect(lastAggregate().groupBy).toEqual({ severityName: true });
426
+ expect(lastAggregate().aggregationTimestampColumnName).toBe("time");
427
+ expect(new Date(lastAggregate().startTimestamp).toISOString()).toBe(
428
+ tableWindow().start,
429
+ );
430
+ expect(new Date(lastAggregate().endTimestamp).toISOString()).toBe(
431
+ tableWindow().end,
432
+ );
433
+ });
434
+
435
+ test("a filter applied in the table recounts the chart with it", async () => {
436
+ renderExplorer();
437
+ await waitForCounts();
438
+
439
+ const filtered: Record<string, unknown> = {
440
+ ...tableProps!.query,
441
+ severityName: new Includes([OcsfSeverity.High, OcsfSeverity.Critical]),
442
+ className: "Authentication",
443
+ };
444
+
445
+ act(() => {
446
+ tableProps!.onQueryChange!(filtered);
447
+ });
448
+ await waitForCounts(2);
449
+
450
+ expect(lastAggregate().query).toBe(filtered);
451
+ });
452
+
453
+ test("shows the window's total and its split by severity", async () => {
454
+ renderExplorer();
455
+ await waitForCounts();
456
+
457
+ expect(totalText()).toBe("7 events");
458
+
459
+ const severities: HTMLElement = screen.getByRole("list", {
460
+ name: "Events by severity",
461
+ });
462
+ expect(
463
+ within(severities)
464
+ .getAllByRole("listitem")
465
+ .map((item: HTMLElement): string => {
466
+ return item.textContent || "";
467
+ }),
468
+ ).toEqual(["Critical1", "High3", "Informational3"]);
469
+ });
470
+
471
+ test("lays out every quarter hour of the day, quiet ones included", async () => {
472
+ renderExplorer();
473
+ await waitForCounts();
474
+
475
+ expect(
476
+ within(screen.getByTestId("bar-chart")).getAllByTestId(/^bucket-/),
477
+ ).toHaveLength(97);
478
+ });
479
+
480
+ test("counts for a window the page has left do not land on the new one", async () => {
481
+ let releaseFirst: (result: AggregatedResult) => void = () => {};
482
+
483
+ aggregateMock.mockImplementationOnce((): Promise<AggregatedResult> => {
484
+ return new Promise<AggregatedResult>(
485
+ (resolve: (result: AggregatedResult) => void) => {
486
+ releaseFirst = resolve;
487
+ },
488
+ );
489
+ });
490
+
491
+ renderExplorer();
492
+ await waitFor(() => {
493
+ expect(aggregateMock).toHaveBeenCalledTimes(1);
494
+ });
495
+
496
+ act(() => {
497
+ pickerProps!.onChange({ range: TimeRange.PAST_ONE_HOUR });
498
+ });
499
+ await waitForCounts(2);
500
+ expect(totalText()).toBe("7 events");
501
+
502
+ await act(async () => {
503
+ releaseFirst({
504
+ data: [row("2026-09-18T11:00:00.000Z", OcsfSeverity.Low, 500)],
505
+ });
506
+ });
507
+
508
+ expect(totalText()).toBe("7 events");
509
+ });
510
+
511
+ test("a failed count says so, and Refresh? counts again", async () => {
512
+ aggregateMock.mockRejectedValueOnce(new Error("ClickHouse is down"));
513
+
514
+ renderExplorer();
515
+
516
+ await waitFor(() => {
517
+ expect(
518
+ screen.getByTestId(`${SECURITY_EVENTS_VOLUME_TEST_ID}-error`),
519
+ ).toHaveTextContent("ClickHouse is down");
520
+ });
521
+
522
+ fireEvent.click(screen.getByTestId("refresh-button"));
523
+ await waitForCounts(2);
524
+
525
+ expect(
526
+ screen.queryByTestId(`${SECURITY_EVENTS_VOLUME_TEST_ID}-error`),
527
+ ).toBeNull();
528
+ expect(totalText()).toBe("7 events");
529
+ });
530
+
531
+ test("an empty window says so in place of an empty axis", async () => {
532
+ resolvesWith([]);
533
+
534
+ renderExplorer();
535
+ await waitForCounts();
536
+
537
+ expect(
538
+ screen.getByTestId(`${SECURITY_EVENTS_VOLUME_TEST_ID}-empty`),
539
+ ).toHaveTextContent("No security events in this time range.");
540
+ expect(totalText()).toBe("0 events");
541
+ });
542
+ });
543
+
544
+ describe("SecurityEventsExplorer: zooming", () => {
545
+ async function dragAcross(from: string, to: string): Promise<void> {
546
+ await act(async () => {
547
+ fireEvent.mouseDown(screen.getByTestId(`bucket-${from}`));
548
+ });
549
+ await act(async () => {
550
+ fireEvent.mouseMove(screen.getByTestId(`bucket-${to}`));
551
+ });
552
+ await act(async () => {
553
+ fireEvent.mouseUp(screen.getByTestId(`bucket-${to}`));
554
+ });
555
+ }
556
+
557
+ test("dragging across the chart zooms the page into the buckets dragged over", async () => {
558
+ renderExplorer();
559
+ await waitForCounts();
560
+
561
+ await dragAcross("2026-09-18T10:00:00.000Z", "2026-09-18T10:30:00.000Z");
562
+ await waitForCounts(2);
563
+
564
+ // The last bucket dragged over is kept whole: 10:30 + 15 minutes.
565
+ expect(tableWindow()).toEqual({
566
+ start: "2026-09-18T10:00:00.000Z",
567
+ end: "2026-09-18T10:45:00.000Z",
568
+ });
569
+ expect(pickerProps!.value.range).toBe(TimeRange.CUSTOM);
570
+ expect(urlParams().get("range")).toBe(TimeRange.CUSTOM);
571
+ expect(urlParams().get("start")).toBe("2026-09-18T10:00:00.000Z");
572
+ expect(urlParams().get("end")).toBe("2026-09-18T10:45:00.000Z");
573
+ });
574
+
575
+ test("double-clicking after a zoom returns to the window before it", async () => {
576
+ renderExplorer();
577
+ await waitForCounts();
578
+
579
+ await dragAcross("2026-09-18T10:00:00.000Z", "2026-09-18T10:30:00.000Z");
580
+ await waitForCounts(2);
581
+
582
+ expect(screen.getByText("Double-click to zoom out")).toBeInTheDocument();
583
+
584
+ fireEvent.doubleClick(
585
+ screen.getByTestId("bar-chart").parentElement!.parentElement!,
586
+ );
587
+ await waitForCounts(3);
588
+
589
+ expect(pickerProps!.value).toEqual({ range: TimeRange.PAST_ONE_DAY });
590
+ expect(urlParams().get("range")).toBe(TimeRange.PAST_ONE_DAY);
591
+ });
592
+
593
+ test("the chart offers drag-to-zoom", async () => {
594
+ renderExplorer();
595
+ await waitForCounts();
596
+
597
+ expect(screen.getByText("Drag to zoom")).toBeInTheDocument();
598
+ });
599
+ });
600
+
601
+ describe("SecurityEventsExplorer: Refresh", () => {
602
+ test("on a relative range, re-reads the window from now", async () => {
603
+ renderExplorer();
604
+ await waitForCounts();
605
+
606
+ const toggleBefore: string | undefined = tableProps!.refreshToggle;
607
+ now = new Date(NOW.getTime() + 5 * MINUTE_MS);
608
+
609
+ fireEvent.click(screen.getByTestId(SECURITY_EVENTS_REFRESH_TEST_ID));
610
+ await waitForCounts(2);
611
+
612
+ expect(tableWindow().end).toBe(now.toISOString());
613
+ expect(new Date(lastAggregate().endTimestamp).toISOString()).toBe(
614
+ now.toISOString(),
615
+ );
616
+ // The query moved, which refetches the table; no second nudge on top.
617
+ expect(tableProps!.refreshToggle).toBe(toggleBefore);
618
+ });
619
+
620
+ test("on a custom range, refetches the same window", async () => {
621
+ window.history.replaceState(
622
+ null,
623
+ "",
624
+ "/dashboard/project/security-events?range=Custom&start=2026-09-10T00:00:00.000Z&end=2026-09-11T00:00:00.000Z",
625
+ );
626
+
627
+ renderExplorer();
628
+ await waitForCounts();
629
+
630
+ const toggleBefore: string | undefined = tableProps!.refreshToggle;
631
+
632
+ fireEvent.click(screen.getByTestId(SECURITY_EVENTS_REFRESH_TEST_ID));
633
+ await waitForCounts(2);
634
+
635
+ expect(tableProps!.refreshToggle).not.toBe(toggleBefore);
636
+ expect(tableWindow()).toEqual({
637
+ start: "2026-09-10T00:00:00.000Z",
638
+ end: "2026-09-11T00:00:00.000Z",
639
+ });
640
+ expect(new Date(lastAggregate().startTimestamp).toISOString()).toBe(
641
+ "2026-09-10T00:00:00.000Z",
642
+ );
643
+ });
644
+ });
645
+
646
+ describe("SecurityEventsExplorer: the table", () => {
647
+ test("is the security events table, without a Time filter or a Refresh of its own", async () => {
648
+ renderExplorer();
649
+ await waitForCounts();
650
+
651
+ expect(tableProps!.id).toBe("security-events-table");
652
+ expect(tableProps!.showRefreshButton).toBe(false);
653
+ expect(
654
+ tableProps!.filters.map((filter: { field: Record<string, boolean> }) => {
655
+ return Object.keys(filter.field)[0];
656
+ }),
657
+ ).not.toContain("time");
658
+ expect(
659
+ tableProps!.filters.map((filter: { title: string }) => {
660
+ return filter.title;
661
+ }),
662
+ ).toEqual(
663
+ expect.arrayContaining(["Severity", "Event Class", "Observable"]),
664
+ );
665
+ });
666
+
667
+ test("with events in the window, never asks when the newest event arrived", async () => {
668
+ renderExplorer();
669
+ await waitForCounts();
670
+
671
+ expect(getListMock).not.toHaveBeenCalled();
672
+ });
673
+
674
+ test("an empty window in a project that has never received an event keeps the setup guide", async () => {
675
+ resolvesWith([]);
676
+
677
+ renderExplorer();
678
+ await waitForCounts();
679
+
680
+ await waitFor(() => {
681
+ expect(tableProps!.noItemsMessage?.type).toBe(SecurityEventsEmptyState);
682
+ });
683
+
684
+ expect(getListMock).toHaveBeenCalledTimes(1);
685
+ const lookup: {
686
+ query: Record<string, unknown>;
687
+ limit: number;
688
+ sort: Record<string, unknown>;
689
+ } = getListMock.mock.calls[0]![0] as never;
690
+ // The whole project, not the window: "has anything ever arrived?"
691
+ expect(lookup.query).toEqual({ projectId: PROJECT_ID });
692
+ expect(lookup.limit).toBe(1);
693
+ expect(lookup.sort).toEqual({ time: SortOrder.Descending });
694
+ });
695
+
696
+ test("an empty window in a project with older events offers the range that reaches them", async () => {
697
+ resolvesWith([]);
698
+ getListMock.mockImplementation(async (): Promise<ListResult<never>> => {
699
+ const event: SecurityEvent = new SecurityEvent();
700
+ event.time = new Date(NOW.getTime() - 3 * DAY_MS);
701
+ return { data: [event as never], count: 1, skip: 0, limit: 1 };
702
+ });
703
+
704
+ renderExplorer();
705
+ await waitForCounts();
706
+
707
+ // The careful message shows first; wait for the lookup to sharpen it.
708
+ await waitFor(() => {
709
+ expect(
710
+ document.getElementById(SECURITY_EVENTS_NO_RESULTS_ID),
711
+ ).toHaveTextContent("The most recent security event arrived");
712
+ });
713
+
714
+ expect(tableProps!.noItemsMessage?.type).toBe(SecurityEventsNoResults);
715
+ const message: HTMLElement = document.getElementById(
716
+ SECURITY_EVENTS_NO_RESULTS_ID,
717
+ ) as HTMLElement;
718
+ expect(message).toHaveTextContent("No security events in this time range");
719
+
720
+ fireEvent.click(
721
+ within(message).getByRole("button", { name: "Show past 1 week" }),
722
+ );
723
+ await waitForCounts(2);
724
+
725
+ expect(pickerProps!.value).toEqual({ range: TimeRange.PAST_ONE_WEEK });
726
+ expect(tableWindow().start).toBe(
727
+ new Date(NOW.getTime() - 7 * DAY_MS).toISOString(),
728
+ );
729
+ });
730
+
731
+ test("until the lookup answers, the empty table says only what is certain", async () => {
732
+ resolvesWith([]);
733
+ getListMock.mockImplementation((): Promise<ListResult<never>> => {
734
+ return new Promise<ListResult<never>>(() => {});
735
+ });
736
+
737
+ renderExplorer();
738
+ await waitForCounts();
739
+
740
+ expect(tableProps!.noItemsMessage?.type).toBe(SecurityEventsNoResults);
741
+ expect(
742
+ document.getElementById(SECURITY_EVENTS_NO_RESULTS_ID),
743
+ ).toHaveTextContent("Try a wider time range");
744
+ });
745
+
746
+ test("a failed lookup falls back to the same careful message", async () => {
747
+ resolvesWith([]);
748
+ getListMock.mockRejectedValue(new Error("nope"));
749
+
750
+ renderExplorer();
751
+ await waitForCounts();
752
+
753
+ await waitFor(() => {
754
+ expect(getListMock).toHaveBeenCalled();
755
+ });
756
+ expect(tableProps!.noItemsMessage?.type).toBe(SecurityEventsNoResults);
757
+ expect(
758
+ document.getElementById(SECURITY_EVENTS_NO_RESULTS_ID),
759
+ ).toHaveTextContent("Try a wider time range");
760
+ });
761
+ });