@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
@@ -1,5 +1,6 @@
1
1
  import Dictionary from "../Dictionary";
2
2
  import { JSONValue } from "../JSON";
3
+ import OcsfSeverity from "./OcsfSeverity";
3
4
 
4
5
  /*
5
6
  * Typed representation of a parsed Sigma rule — the subset OneUptime's
@@ -17,6 +18,56 @@ export enum SigmaLevel {
17
18
  Critical = "critical",
18
19
  }
19
20
 
21
+ /*
22
+ * The level a rule gets when its YAML has no `level:` or one outside the
23
+ * enum above. The parser applies it; the dashboard's rule guide states it.
24
+ */
25
+ export const SIGMA_DEFAULT_LEVEL: SigmaLevel = SigmaLevel.Medium;
26
+
27
+ /*
28
+ * Sigma level -> OCSF severity stamped on a rule's Detection Finding rows.
29
+ * Lives here rather than in the evaluator so the dashboard's rule guide
30
+ * renders its severity table from the same map the engine writes with.
31
+ */
32
+ export const SIGMA_LEVEL_TO_OCSF_SEVERITY: Record<SigmaLevel, OcsfSeverity> = {
33
+ [SigmaLevel.Informational]: OcsfSeverity.Informational,
34
+ [SigmaLevel.Low]: OcsfSeverity.Low,
35
+ [SigmaLevel.Medium]: OcsfSeverity.Medium,
36
+ [SigmaLevel.High]: OcsfSeverity.High,
37
+ [SigmaLevel.Critical]: OcsfSeverity.Critical,
38
+ };
39
+
40
+ /*
41
+ * Levels that rank onto a project's MOST severe alert/incident severity
42
+ * when no severity is set on the rule and none is named after the level;
43
+ * every other level ranks onto the least severe.
44
+ */
45
+ export function isSevereSigmaLevel(level: SigmaLevel): boolean {
46
+ return level === SigmaLevel.Critical || level === SigmaLevel.High;
47
+ }
48
+
49
+ /*
50
+ * Field modifiers (`field|modifier: value`) the parser accepts. Anything
51
+ * else is rejected at save time — listed here so the dashboard's rule
52
+ * guide cannot advertise a modifier the parser refuses, or miss one it
53
+ * takes.
54
+ */
55
+ export const SIGMA_SUPPORTED_MODIFIERS: ReadonlyArray<string> = [
56
+ "contains",
57
+ "startswith",
58
+ "endswith",
59
+ "all",
60
+ "re",
61
+ "cased",
62
+ "gt",
63
+ "gte",
64
+ "lt",
65
+ "lte",
66
+ "cidr",
67
+ "exists",
68
+ "windash",
69
+ ];
70
+
20
71
  /*
21
72
  * One `field|modifier: value` requirement inside a selection map. `values`
22
73
  * always has at least one entry; multiple entries are OR-ed (AND-ed when
@@ -105,6 +105,24 @@ export function ocsfSeverityForConfidence(confidence: number): OcsfSeverity {
105
105
  export const THREAT_INTEL_MINIMUM_CONFIDENCE_MIN: number = 0;
106
106
  export const THREAT_INTEL_MINIMUM_CONFIDENCE_MAX: number = 100;
107
107
 
108
+ /*
109
+ * Save-time bounds and default for ThreatIntelFeed.pollIntervalInMinutes —
110
+ * shared by the server validator, the poller's fallback and the dashboard
111
+ * form, so the three cannot drift apart.
112
+ */
113
+ export const THREAT_INTEL_POLL_INTERVAL_MIN_IN_MINUTES: number = 1;
114
+ export const THREAT_INTEL_POLL_INTERVAL_MAX_IN_MINUTES: number = 1440;
115
+ export const THREAT_INTEL_DEFAULT_POLL_INTERVAL_IN_MINUTES: number = 60;
116
+
117
+ // Cap on one match evaluation's scan, whatever lastEvaluatedAt says.
118
+ export const THREAT_INTEL_MATCH_MAX_LOOKBACK_IN_MINUTES: number = 24 * 60;
119
+
120
+ // First-ever match evaluation window for a feed.
121
+ export const THREAT_INTEL_FIRST_MATCH_WINDOW_IN_MINUTES: number = 15;
122
+
123
+ // One alert per distinct indicator value per cycle, at most.
124
+ export const THREAT_INTEL_MAX_INDICATORS_PER_EVALUATION: number = 100;
125
+
108
126
  /*
109
127
  * Indicators whose STIX object carries no valid_until stay active this
110
128
  * long after valid_from. STIX says "valid until revoked"; unbounded
@@ -1,3 +1,4 @@
1
+ import { handleAuthenticatedLinkClick } from "../../Utils/OpenAuthenticatedUrl";
1
2
  import React, { FunctionComponent, ReactElement } from "react";
2
3
 
3
4
  export interface EventAttachment {
@@ -12,6 +13,14 @@ export interface EventAttachmentListProps {
12
13
  showHeader?: boolean;
13
14
  showCount?: boolean;
14
15
  className?: string;
16
+ /*
17
+ * Set when the download URLs are behind a session that can lapse while the
18
+ * page is open (a private status page). A click then refreshes the session
19
+ * before the new tab loads the file, so a reader who has had the page open
20
+ * past the access token's lifetime gets the attachment, not a 401. Left
21
+ * unset, the cards are plain links.
22
+ */
23
+ refreshSession?: (() => Promise<boolean>) | undefined;
15
24
  }
16
25
 
17
26
  function getAttachmentExtensionLabel(fileName?: string | null): string | null {
@@ -31,12 +40,13 @@ function getAttachmentExtensionLabel(fileName?: string | null): string | null {
31
40
 
32
41
  type AttachmentCardProps = {
33
42
  attachment: EventAttachment;
43
+ refreshSession?: (() => Promise<boolean>) | undefined;
34
44
  };
35
45
 
36
46
  const AttachmentCard: FunctionComponent<AttachmentCardProps> = (
37
47
  props: AttachmentCardProps,
38
48
  ): ReactElement => {
39
- const { attachment } = props;
49
+ const { attachment, refreshSession } = props;
40
50
  const extensionLabel: string | null = getAttachmentExtensionLabel(
41
51
  attachment.name,
42
52
  );
@@ -47,6 +57,17 @@ const AttachmentCard: FunctionComponent<AttachmentCardProps> = (
47
57
  href={attachment.downloadUrl}
48
58
  target="_blank"
49
59
  rel="noopener noreferrer"
60
+ onClick={
61
+ refreshSession
62
+ ? (event: React.MouseEvent<HTMLAnchorElement>): void => {
63
+ handleAuthenticatedLinkClick(
64
+ event,
65
+ attachment.downloadUrl,
66
+ refreshSession,
67
+ );
68
+ }
69
+ : undefined
70
+ }
50
71
  title={attachment.name}
51
72
  className="group flex items-center justify-between gap-3 rounded-lg border border-gray-200 bg-white px-3 py-2 text-sm text-gray-900 transition hover:border-gray-300 hover:bg-gray-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-gray-200"
52
73
  >
@@ -81,6 +102,7 @@ const EventAttachmentList: FunctionComponent<EventAttachmentListProps> = (
81
102
  showHeader = true,
82
103
  showCount = true,
83
104
  className = "",
105
+ refreshSession,
84
106
  } = props;
85
107
 
86
108
  if (!attachments || attachments.length === 0) {
@@ -90,7 +112,13 @@ const EventAttachmentList: FunctionComponent<EventAttachmentListProps> = (
90
112
  const attachmentsList: ReactElement = (
91
113
  <ul className="space-y-2">
92
114
  {attachments.map((attachment: EventAttachment, index: number) => {
93
- return <AttachmentCard attachment={attachment} key={index} />;
115
+ return (
116
+ <AttachmentCard
117
+ attachment={attachment}
118
+ refreshSession={refreshSession}
119
+ key={index}
120
+ />
121
+ );
94
122
  })}
95
123
  </ul>
96
124
  );
@@ -193,8 +193,16 @@ const DashboardVariableControl: FunctionComponent<ComponentProps> = (
193
193
  });
194
194
  const selectedValue: string =
195
195
  variable.selectedValue ?? variable.defaultValue ?? "";
196
+ /*
197
+ * With no option for its value the browser would show "All", while
198
+ * VariableInterpolation still filters every widget by that value. A project
199
+ * label can be deleted or disallowed. A telemetry attribute only lists the
200
+ * first 100 values seen in the last day, and its default is free text, so
201
+ * its value can be missing from the list and still match data. Skipped
202
+ * while those values load: the select reads "Loading…" until they arrive.
203
+ */
196
204
  const isUnavailableSelection: boolean = Boolean(
197
- isProjectLabel &&
205
+ (isProjectLabel || (isTelemetryAttribute && !props.isLoadingOptions)) &&
198
206
  selectedValue &&
199
207
  !options.some((option: DashboardVariableOption) => {
200
208
  return option.value === selectedValue;
@@ -253,7 +261,9 @@ const DashboardVariableControl: FunctionComponent<ComponentProps> = (
253
261
  {props.isLoadingOptions ? "Loading…" : "All"}
254
262
  </option>
255
263
  {isUnavailableSelection && (
256
- <option value={selectedValue}>Unavailable label</option>
264
+ <option value={selectedValue}>
265
+ {isProjectLabel ? "Unavailable label" : selectedValue}
266
+ </option>
257
267
  )}
258
268
  {options.map((option: DashboardVariableOption) => {
259
269
  return (
@@ -569,13 +569,18 @@ const Dropdown: FunctionComponent<ComponentProps> = (
569
569
  return;
570
570
  }
571
571
 
572
+ // Uncontrolled selections belong to this component, even if options refresh.
573
+ if (!("value" in props)) {
574
+ return;
575
+ }
576
+
572
577
  const value: DropdownOption | Array<DropdownOption> | undefined =
573
578
  getDropdownOptionFromValue(
574
579
  props.value === null ? undefined : props.value,
575
580
  );
576
581
 
577
582
  setValue(value);
578
- }, [props.value]);
583
+ }, [props.value, props.options]);
579
584
 
580
585
  const menuPortalTarget: HTMLElement | null =
581
586
  typeof document === "undefined" ? null : document.body;
@@ -240,6 +240,18 @@ const EditionLabel: FunctionComponent<ComponentProps> = (
240
240
  new Route("/global-config/license"),
241
241
  );
242
242
 
243
+ /*
244
+ * The route also serves the login page, so on its own it answers a
245
+ * caller with no session with the reduced anonymous payload and a 200.
246
+ * Inside a signed-in app that caller is us with an expired session,
247
+ * and the reduced payload reads as "no license, no instances". Saying
248
+ * we expect to be signed in makes the server answer 401 instead,
249
+ * which the API client refreshes and replays.
250
+ */
251
+ if (UserUtil.isLoggedIn()) {
252
+ licenseUrl.addQueryParam("signedIn", "true");
253
+ }
254
+
243
255
  const response: HTTPResponse<JSONObject> | HTTPErrorResponse =
244
256
  await API.fetch<JSONObject>({
245
257
  method: HTTPMethod.GET,
@@ -58,6 +58,11 @@ export interface ComponentProps {
58
58
  eventSecondDescription: string;
59
59
  labels?: Array<EventItemLabel> | undefined;
60
60
  eventAttachments?: Array<TimelineAttachment> | undefined;
61
+ /*
62
+ * Handed to every EventAttachmentList this item renders: the event's own
63
+ * attachments and each timeline note's. See EventAttachmentList.
64
+ */
65
+ attachmentRefreshSession?: (() => Promise<boolean>) | undefined;
61
66
  }
62
67
 
63
68
  const EventItem: FunctionComponent<ComponentProps> = (
@@ -116,7 +121,10 @@ const EventItem: FunctionComponent<ComponentProps> = (
116
121
  )}
117
122
 
118
123
  {props.eventAttachments && props.eventAttachments.length > 0 && (
119
- <EventAttachmentList attachments={props.eventAttachments} />
124
+ <EventAttachmentList
125
+ attachments={props.eventAttachments}
126
+ refreshSession={props.attachmentRefreshSession}
127
+ />
120
128
  )}
121
129
 
122
130
  {props.eventSecondDescription && (
@@ -320,6 +328,9 @@ const EventItem: FunctionComponent<ComponentProps> = (
320
328
  item.attachments.length > 0 && (
321
329
  <EventAttachmentList
322
330
  attachments={item.attachments}
331
+ refreshSession={
332
+ props.attachmentRefreshSession
333
+ }
323
334
  variant="inline"
324
335
  showHeader={false}
325
336
  showCount={false}
@@ -11,6 +11,7 @@ import {
11
11
  DropdownValue,
12
12
  } from "../Dropdown/Dropdown";
13
13
  import ErrorMessage from "../ErrorMessage/ErrorMessage";
14
+ import CollapsibleFormSection from "./CollapsibleFormSection";
14
15
  import FormField from "./Fields/FormField";
15
16
  import FormSummary from "./FormSummary";
16
17
  import Steps from "./Steps/Steps";
@@ -222,6 +223,7 @@ const BasicForm: ForwardRefExoticComponent<any> = forwardRef(
222
223
 
223
224
  const [errors, setErrors] = useState<Dictionary<string>>({});
224
225
  const [touched, setTouched] = useState<Dictionary<boolean>>({});
226
+ const [validationAttempt, setValidationAttempt] = useState<number>(0);
225
227
 
226
228
  useEffect(() => {
227
229
  setFormSteps(getVisibleFormSteps());
@@ -402,6 +404,9 @@ const BasicForm: ForwardRefExoticComponent<any> = forwardRef(
402
404
  const submitForm: () => void = (): void => {
403
405
  // check for any boolean values and if they don't exist in values - mark them as false.
404
406
 
407
+ setValidationAttempt((attempt: number) => {
408
+ return attempt + 1;
409
+ });
405
410
  setAllTouched();
406
411
 
407
412
  const validationErrors: Dictionary<string> = validate(
@@ -592,41 +597,16 @@ const BasicForm: ForwardRefExoticComponent<any> = forwardRef(
592
597
  field.fieldType === FormFieldSchemaType.MultiSelectDropdown &&
593
598
  (values as any)[fieldName]
594
599
  ) {
595
- const flatDropdownOptions: Array<DropdownOption> =
596
- field.dropdownOptions?.flatMap(
597
- (item: DropdownOption | DropdownOptionGroup) => {
598
- if (
599
- "options" in item &&
600
- Array.isArray((item as DropdownOptionGroup).options)
601
- ) {
602
- return (item as DropdownOptionGroup).options;
603
- }
604
- return [item as DropdownOption];
605
- },
606
- ) || [];
607
-
608
- const dropdownOptions: Array<DropdownOption> =
609
- flatDropdownOptions.filter((option: DropdownOption) => {
610
- let valueToCompare: Array<DropdownValue> = [
611
- ...(values as any)[fieldName],
612
- ];
613
-
614
- valueToCompare = valueToCompare.map((item: DropdownValue) => {
615
- if ((item as any) instanceof ObjectID) {
616
- return item.toString();
617
- }
618
-
619
- return item;
620
- });
621
-
622
- return valueToCompare.includes(option.value);
623
- });
624
-
625
- (values as any)[fieldName] = dropdownOptions.map(
626
- (option: DropdownOption) => {
627
- return option.value;
628
- },
629
- );
600
+ /*
601
+ * Options can be loaded lazily for a later step or omit entities the
602
+ * user cannot browse. Preserve every stored selection just as a single
603
+ * dropdown does; an option list is not an authorization to clear IDs.
604
+ */
605
+ (values as any)[fieldName] = (
606
+ (values as any)[fieldName] as Array<DropdownValue | ObjectID>
607
+ ).map((value: DropdownValue | ObjectID): DropdownValue => {
608
+ return value instanceof ObjectID ? value.toString() : value;
609
+ });
630
610
  }
631
611
 
632
612
  // if the field is still null but has a default value then... have the default initial value
@@ -742,102 +722,147 @@ const BasicForm: ForwardRefExoticComponent<any> = forwardRef(
742
722
  const activeColumns: number =
743
723
  currentStep?.columns || props.showAsColumns || 1;
744
724
  const fullRowSpan: string = `md:col-span-${activeColumns}`;
725
+ const visibleFields: Fields<T> = formFields.filter(
726
+ (field: Field<T>): boolean => {
727
+ return (
728
+ (!currentFormStepId ||
729
+ field.stepId === currentFormStepId) &&
730
+ (!field.showIf ||
731
+ field.showIf(refCurrentValue.current))
732
+ );
733
+ },
734
+ );
735
+ const fieldGroups: Array<Fields<T>> = [];
736
+
737
+ for (const field of visibleFields) {
738
+ const previousGroup: Fields<T> | undefined =
739
+ fieldGroups[fieldGroups.length - 1];
740
+ if (
741
+ field.collapsibleSection &&
742
+ previousGroup?.[0]?.collapsibleSection?.id ===
743
+ field.collapsibleSection.id
744
+ ) {
745
+ previousGroup.push(field);
746
+ } else {
747
+ fieldGroups.push([field]);
748
+ }
749
+ }
750
+
751
+ const renderField: (
752
+ field: Field<T>,
753
+ index: number,
754
+ ) => ReactElement = (
755
+ field: Field<T>,
756
+ index: number,
757
+ ): ReactElement => {
758
+ const fieldName: string = getFieldName(field);
759
+ return (
760
+ <Fragment key={fieldName}>
761
+ {field.sectionTitle && (
762
+ <div
763
+ className={`${fullRowSpan} mt-4 pt-5 first:mt-0 first:pt-0 border-t first:border-t-0 border-gray-200`}
764
+ >
765
+ <h3 className="text-base font-semibold text-gray-900">
766
+ {translateString(field.sectionTitle) ??
767
+ field.sectionTitle}
768
+ </h3>
769
+ {field.sectionDescription && (
770
+ <p className="mt-1 text-sm text-gray-500">
771
+ {typeof field.sectionDescription === "string"
772
+ ? translateString(
773
+ field.sectionDescription,
774
+ ) ?? field.sectionDescription
775
+ : field.sectionDescription}
776
+ </p>
777
+ )}
778
+ </div>
779
+ )}
780
+ <div
781
+ className={
782
+ field.spanFullRow ? fullRowSpan : undefined
783
+ }
784
+ >
785
+ <FormField<T>
786
+ field={field}
787
+ fieldName={fieldName}
788
+ index={index}
789
+ error={errors[fieldName] || ""}
790
+ touched={touched[fieldName] || false}
791
+ isDisabled={
792
+ isLoading ||
793
+ (isDropdownOptionsLoading &&
794
+ isDropdownField(field)) ||
795
+ false
796
+ }
797
+ currentValues={refCurrentValue.current}
798
+ setFieldValue={setFieldValue}
799
+ setFieldTouched={setFieldTouched}
800
+ submitForm={submitForm}
801
+ disableAutofocus={props.disableAutofocus || false}
802
+ setFormValues={(values: FormValues<T>) => {
803
+ refCurrentValue.current = values;
804
+ setCurrentValue(refCurrentValue.current);
805
+ }}
806
+ />
807
+ {field.footerElement}
808
+ {field.getFooterElement &&
809
+ field.getFooterElement(
810
+ refCurrentValue.current,
811
+ touched[fieldName]
812
+ ? errors[fieldName] || undefined
813
+ : undefined,
814
+ )}
815
+ </div>
816
+ </Fragment>
817
+ );
818
+ };
819
+ let fieldIndex: number = 0;
820
+
745
821
  return (
746
822
  <div
747
823
  className={`grid md:grid-cols-${activeColumns} grid-cols-1 gap-x-4 gap-y-3`}
748
824
  >
749
- {formFields &&
750
- formFields
751
- .filter((field: Field<T>) => {
752
- if (currentFormStepId) {
753
- return field.stepId === currentFormStepId;
825
+ {fieldGroups.map((group: Fields<T>): ReactElement => {
826
+ const firstField: Field<T> = group[0]!;
827
+ const fields: Array<ReactElement> = group.map(
828
+ (field: Field<T>): ReactElement => {
829
+ return renderField(field, fieldIndex++);
830
+ },
831
+ );
832
+
833
+ if (!firstField.collapsibleSection) {
834
+ return fields[0]!;
835
+ }
836
+
837
+ return (
838
+ <CollapsibleFormSection
839
+ key={`${firstField.collapsibleSection.id}-${getFieldName(firstField)}`}
840
+ title={firstField.collapsibleSection.title}
841
+ description={
842
+ firstField.collapsibleSection.description
754
843
  }
755
-
756
- return true;
757
- })
758
- .filter((field: Field<T>) => {
759
- const currentValues: FormValues<T> =
760
- refCurrentValue.current;
761
- if (
762
- field.showIf &&
763
- !field.showIf(currentValues)
764
- ) {
765
- return false;
766
- }
767
-
768
- return true;
769
- })
770
- .map((field: Field<T>, i: number) => {
771
- const fieldName: string = getFieldName(field);
772
- return (
773
- <Fragment key={fieldName}>
774
- {field.sectionTitle && (
775
- <div
776
- className={`${fullRowSpan} mt-4 pt-5 first:mt-0 first:pt-0 border-t first:border-t-0 border-gray-200`}
777
- >
778
- <h3 className="text-base font-semibold text-gray-900">
779
- {translateString(field.sectionTitle) ??
780
- field.sectionTitle}
781
- </h3>
782
- {field.sectionDescription && (
783
- <p className="mt-1 text-sm text-gray-500">
784
- {typeof field.sectionDescription ===
785
- "string"
786
- ? translateString(
787
- field.sectionDescription,
788
- ) ?? field.sectionDescription
789
- : field.sectionDescription}
790
- </p>
791
- )}
792
- </div>
793
- )}
794
- <div
795
- className={
796
- field.spanFullRow
797
- ? fullRowSpan
798
- : undefined
799
- }
800
- >
801
- <FormField<T>
802
- field={field}
803
- fieldName={fieldName}
804
- index={i}
805
- error={errors[fieldName] || ""}
806
- touched={touched[fieldName] || false}
807
- isDisabled={
808
- isLoading ||
809
- (isDropdownOptionsLoading &&
810
- isDropdownField(field)) ||
811
- false
812
- }
813
- currentValues={refCurrentValue.current}
814
- setFieldValue={setFieldValue}
815
- setFieldTouched={setFieldTouched}
816
- submitForm={submitForm}
817
- disableAutofocus={
818
- props.disableAutofocus || false
819
- }
820
- setFormValues={(
821
- values: FormValues<T>,
822
- ) => {
823
- refCurrentValue.current = values;
824
- setCurrentValue(
825
- refCurrentValue.current,
826
- );
827
- }}
828
- />
829
- {field.footerElement}
830
- {field.getFooterElement &&
831
- field.getFooterElement(
832
- refCurrentValue.current,
833
- touched[fieldName]
834
- ? errors[fieldName] || undefined
835
- : undefined,
836
- )}
837
- </div>
838
- </Fragment>
839
- );
840
- })}
844
+ isConfigured={firstField.collapsibleSection.isConfigured(
845
+ refCurrentValue.current,
846
+ )}
847
+ hasError={group.some(
848
+ (field: Field<T>): boolean => {
849
+ const fieldName: string = getFieldName(field);
850
+ return Boolean(
851
+ touched[fieldName] && errors[fieldName],
852
+ );
853
+ },
854
+ )}
855
+ validationAttempt={validationAttempt}
856
+ className={fullRowSpan}
857
+ >
858
+ <div
859
+ className={`grid md:grid-cols-${activeColumns} grid-cols-1 gap-x-4 gap-y-3`}
860
+ >
861
+ {fields}
862
+ </div>
863
+ </CollapsibleFormSection>
864
+ );
865
+ })}
841
866
 
842
867
  {/* If Summary, show Model detail */}
843
868
 
@@ -0,0 +1,63 @@
1
+ import useTranslateValue from "../../Utils/Translation";
2
+ import CollapsibleSection from "../CollapsibleSection/CollapsibleSection";
3
+ import React, {
4
+ FunctionComponent,
5
+ ReactElement,
6
+ useEffect,
7
+ useState,
8
+ } from "react";
9
+
10
+ export interface ComponentProps {
11
+ title: string;
12
+ description?: string | undefined;
13
+ isConfigured: boolean;
14
+ hasError: boolean;
15
+ validationAttempt: number;
16
+ className: string;
17
+ children: ReactElement;
18
+ }
19
+
20
+ const CollapsibleFormSection: FunctionComponent<ComponentProps> = (
21
+ props: ComponentProps,
22
+ ): ReactElement => {
23
+ const { translateString } = useTranslateValue();
24
+ const [isCollapsed, setIsCollapsed] = useState<boolean>(!props.isConfigured);
25
+
26
+ useEffect(() => {
27
+ // Field defaults can arrive after the form has loaded its field definitions.
28
+ if (props.isConfigured) {
29
+ setIsCollapsed(false);
30
+ }
31
+ }, [props.isConfigured]);
32
+
33
+ useEffect(() => {
34
+ if (props.hasError) {
35
+ setIsCollapsed(false);
36
+ }
37
+ }, [props.hasError, props.validationAttempt]);
38
+
39
+ return (
40
+ <CollapsibleSection
41
+ title={translateString(props.title) ?? props.title}
42
+ description={
43
+ props.description
44
+ ? translateString(props.description) ?? props.description
45
+ : undefined
46
+ }
47
+ variant="bordered"
48
+ className={props.className}
49
+ isCollapsed={isCollapsed}
50
+ onToggle={setIsCollapsed}
51
+ badge={
52
+ props.isConfigured
53
+ ? translateString("Configured") ?? "Configured"
54
+ : undefined
55
+ }
56
+ >
57
+ {/* Keep editors mounted without leaving collapsed controls focusable. */}
58
+ <div hidden={isCollapsed}>{props.children}</div>
59
+ </CollapsibleSection>
60
+ );
61
+ };
62
+
63
+ export default CollapsibleFormSection;