@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
@@ -7,9 +7,40 @@ import ReadPermission, { CheckReadPermissionType } from "./ReadPermission";
7
7
  import UpdatePermission from "./UpdatePermission";
8
8
  import BaseModel from "../../../../Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel";
9
9
  import DatabaseCommonInteractionProps from "../../../../Types/BaseDatabase/DatabaseCommonInteractionProps";
10
+ import DatabaseCommonInteractionPropsUtil from "../../../../Types/BaseDatabase/DatabaseCommonInteractionPropsUtil";
11
+ import NotAuthenticatedException from "../../../../Types/Exception/NotAuthenticatedException";
12
+ import NotAuthorizedException from "../../../../Types/Exception/NotAuthorizedException";
10
13
  import CaptureSpan from "../../../Utils/Telemetry/CaptureSpan";
11
14
 
12
15
  export default class ModelPermission {
16
+ /*
17
+ * A refusal of a caller with no credentials at all is a 401.
18
+ *
19
+ * The login check near the top of every permission check passes an
20
+ * anonymous caller straight through on models that are readable (or
21
+ * creatable) by Public - Probe, AIAgent, LlmProvider and friends - and the
22
+ * column, select and query checks that follow then refuse it with 422
23
+ * NotAuthorizedException. For the dashboard that caller is a signed-in user
24
+ * whose access-token cookie expired, and only a 401 makes the browser client
25
+ * refresh the session and replay the request. Callers with credentials keep
26
+ * the 422 they always got; the message is kept either way.
27
+ */
28
+ private static toAnonymousRefusal(
29
+ error: unknown,
30
+ props: DatabaseCommonInteractionProps,
31
+ ): unknown {
32
+ if (
33
+ error instanceof NotAuthorizedException &&
34
+ !props.isRoot &&
35
+ !props.isMasterAdmin &&
36
+ DatabaseCommonInteractionPropsUtil.isAnonymous(props)
37
+ ) {
38
+ return new NotAuthenticatedException(error.message);
39
+ }
40
+
41
+ return error;
42
+ }
43
+
13
44
  @CaptureSpan()
14
45
  public static async checkDeletePermissionByModel<
15
46
  TBaseModel extends BaseModel,
@@ -18,7 +49,11 @@ export default class ModelPermission {
18
49
  fetchModelWithAccessControlIds: () => Promise<TBaseModel | null>;
19
50
  props: DatabaseCommonInteractionProps;
20
51
  }): Promise<void> {
21
- return DeletePermission.checkDeletePermissionByModel(data);
52
+ try {
53
+ return await DeletePermission.checkDeletePermissionByModel(data);
54
+ } catch (error) {
55
+ throw ModelPermission.toAnonymousRefusal(error, data.props);
56
+ }
22
57
  }
23
58
 
24
59
  @CaptureSpan()
@@ -29,7 +64,11 @@ export default class ModelPermission {
29
64
  fetchModelWithAccessControlIds: () => Promise<TBaseModel | null>;
30
65
  props: DatabaseCommonInteractionProps;
31
66
  }): Promise<void> {
32
- return UpdatePermission.checkUpdatePermissionByModel(data);
67
+ try {
68
+ return await UpdatePermission.checkUpdatePermissionByModel(data);
69
+ } catch (error) {
70
+ throw ModelPermission.toAnonymousRefusal(error, data.props);
71
+ }
33
72
  }
34
73
 
35
74
  @CaptureSpan()
@@ -38,7 +77,15 @@ export default class ModelPermission {
38
77
  query: Query<TBaseModel>,
39
78
  props: DatabaseCommonInteractionProps,
40
79
  ): Promise<Query<TBaseModel>> {
41
- return DeletePermission.checkDeletePermission(modelType, query, props);
80
+ try {
81
+ return await DeletePermission.checkDeletePermission(
82
+ modelType,
83
+ query,
84
+ props,
85
+ );
86
+ } catch (error) {
87
+ throw ModelPermission.toAnonymousRefusal(error, props);
88
+ }
42
89
  }
43
90
 
44
91
  @CaptureSpan()
@@ -48,12 +95,16 @@ export default class ModelPermission {
48
95
  data: QueryDeepPartialEntity<TBaseModel>,
49
96
  props: DatabaseCommonInteractionProps,
50
97
  ): Promise<Query<TBaseModel>> {
51
- return UpdatePermission.checkUpdatePermissions(
52
- modelType,
53
- query,
54
- data,
55
- props,
56
- );
98
+ try {
99
+ return await UpdatePermission.checkUpdatePermissions(
100
+ modelType,
101
+ query,
102
+ data,
103
+ props,
104
+ );
105
+ } catch (error) {
106
+ throw ModelPermission.toAnonymousRefusal(error, props);
107
+ }
57
108
  }
58
109
 
59
110
  @CaptureSpan()
@@ -62,7 +113,11 @@ export default class ModelPermission {
62
113
  data: TBaseModel,
63
114
  props: DatabaseCommonInteractionProps,
64
115
  ): void {
65
- return CreatePermission.checkCreatePermissions(modelType, data, props);
116
+ try {
117
+ return CreatePermission.checkCreatePermissions(modelType, data, props);
118
+ } catch (error) {
119
+ throw ModelPermission.toAnonymousRefusal(error, props);
120
+ }
66
121
  }
67
122
 
68
123
  @CaptureSpan()
@@ -72,6 +127,15 @@ export default class ModelPermission {
72
127
  select: Select<TBaseModel> | null,
73
128
  props: DatabaseCommonInteractionProps,
74
129
  ): Promise<CheckReadPermissionType<TBaseModel>> {
75
- return ReadPermission.checkReadPermission(modelType, query, select, props);
130
+ try {
131
+ return await ReadPermission.checkReadPermission(
132
+ modelType,
133
+ query,
134
+ select,
135
+ props,
136
+ );
137
+ } catch (error) {
138
+ throw ModelPermission.toAnonymousRefusal(error, props);
139
+ }
76
140
  }
77
141
  }
@@ -168,35 +168,31 @@ export default class TablePermission {
168
168
  const modelPermissions: Array<Permission> =
169
169
  TablePermission.getTablePermission(modelType, type);
170
170
 
171
- const intersectingPermissions: Array<Permission> =
172
- PermissionHelper.getIntersectingPermissions(
173
- userPermissions.map((userPermission: UserPermission) => {
174
- return userPermission.permission;
175
- }) || [],
176
- modelPermissions,
177
- );
178
-
179
- if (intersectingPermissions && intersectingPermissions.length > 0) {
180
- for (const permission of intersectingPermissions) {
181
- const userPermission: UserPermission = userPermissions.find(
182
- (userPermission: UserPermission) => {
183
- return userPermission.permission === permission;
184
- },
185
- ) as UserPermission;
186
-
187
- if (
188
- userPermission &&
171
+ /*
172
+ * The user gets one block row per TeamPermission across all of their
173
+ * teams, unmerged and unordered, so the same permission can be blocked
174
+ * both for some labels and for the whole table. A row without labels
175
+ * blocks the whole table and must win whichever row comes first:
176
+ * ReadPermission and AccessControlPermission only enforce the labelled
177
+ * rows, so an unlabelled row missed here is enforced nowhere.
178
+ */
179
+ const tableWideBlock: UserPermission | undefined = userPermissions.find(
180
+ (userPermission: UserPermission) => {
181
+ return (
182
+ modelPermissions.includes(userPermission.permission) &&
189
183
  (!userPermission.labelIds || userPermission.labelIds.length === 0)
190
- ) {
191
- throw new NotAuthorizedException(
192
- `You are not authorized to ${type} ${
193
- new modelType().singularName
194
- } because ${
195
- userPermission.permission
196
- } is in your team's permission block list.`,
197
- );
198
- }
199
- }
184
+ );
185
+ },
186
+ );
187
+
188
+ if (tableWideBlock) {
189
+ throw new NotAuthorizedException(
190
+ `You are not authorized to ${type} ${
191
+ new modelType().singularName
192
+ } because ${
193
+ tableWideBlock.permission
194
+ } is in your team's permission block list.`,
195
+ );
200
196
  }
201
197
  }
202
198
  }
@@ -1,4 +1,5 @@
1
1
  import DatabaseCommonInteractionProps from "../../../Types/BaseDatabase/DatabaseCommonInteractionProps";
2
+ import DatabaseCommonInteractionPropsUtil from "../../../Types/BaseDatabase/DatabaseCommonInteractionPropsUtil";
2
3
  import NotAuthorizedException from "../../../Types/Exception/NotAuthorizedException";
3
4
 
4
5
  /*
@@ -16,6 +17,13 @@ export function pinQueryToRequestingUser<TQuery>(
16
17
  return query;
17
18
  }
18
19
 
20
+ /*
21
+ * No credentials at all is an expired session, not someone else's data:
22
+ * 401 so the client refreshes. The countBy overrides reach this before the
23
+ * permission layer's own login check does.
24
+ */
25
+ DatabaseCommonInteractionPropsUtil.assertCredentialsPresent(props);
26
+
19
27
  if (!props.userId) {
20
28
  throw new NotAuthorizedException(
21
29
  "AI conversations are personal and can only be accessed by the user who created them.",
@@ -1,4 +1,5 @@
1
1
  import DatabaseCommonInteractionProps from "../../../Types/BaseDatabase/DatabaseCommonInteractionProps";
2
+ import DatabaseCommonInteractionPropsUtil from "../../../Types/BaseDatabase/DatabaseCommonInteractionPropsUtil";
2
3
  import { FindWhereProperty } from "../../../Types/BaseDatabase/Query";
3
4
  import NotAuthorizedException from "../../../Types/Exception/NotAuthorizedException";
4
5
  import AIRunType from "../../../Types/AI/AIRunType";
@@ -57,6 +58,13 @@ export function getAIRunPrivacyRaw(
57
58
  * /ai-run nor /code-fix-run grants today. That is a separate product
58
59
  * decision and must not ride in as a side effect of this filter.
59
60
  */
61
+ /*
62
+ * No credentials at all is an expired session, not someone else's data:
63
+ * 401 so the client refreshes. The countBy overrides reach this before the
64
+ * permission layer's own login check does.
65
+ */
66
+ DatabaseCommonInteractionPropsUtil.assertCredentialsPresent(props);
67
+
60
68
  if (!props.userId) {
61
69
  throw new NotAuthorizedException(
62
70
  "AI runs are personal and can only be accessed by the user who created them.",
@@ -0,0 +1,61 @@
1
+ import UserMiddleware from "../Middleware/UserAuthorization";
2
+ import { ExpressRequest, ExpressResponse } from "./Express";
3
+ import JSONWebToken from "./JsonWebToken";
4
+ import logger from "./Logger";
5
+ import Response from "./Response";
6
+ import NotAuthorizedException from "../../Types/Exception/NotAuthorizedException";
7
+ import { JSONObject } from "../../Types/JSON";
8
+ import JSONWebTokenData from "../../Types/JsonWebTokenData";
9
+
10
+ export const NOT_A_MASTER_ADMIN_MESSAGE: string =
11
+ "Unauthorized: Only master admins can access the admin dashboard.";
12
+
13
+ /*
14
+ * Gate for the Admin Dashboard's index page (the HTML shell, not its APIs).
15
+ *
16
+ * It refuses only a caller it can positively identify as NOT a master admin.
17
+ * A missing access token, or one that no longer decodes, is served the shell:
18
+ * the access-token cookie expires with the JWT inside it, so an admin who
19
+ * reloads a tab left open past the token lifetime arrives here with no token
20
+ * at all, and answering that with a 422 JSON page meant the app never loaded
21
+ * and so never got to refresh the session. The shell holds nothing the public
22
+ * static bundle does not; once it loads, the SPA sends a signed-out visitor to
23
+ * the login page, and every admin API it calls refreshes an expired session
24
+ * (or answers 401) on its own.
25
+ */
26
+ export const ensureMasterAdminPageAccess: (data: {
27
+ req: ExpressRequest;
28
+ res: ExpressResponse;
29
+ service: string;
30
+ }) => Promise<JSONObject> = async (data: {
31
+ req: ExpressRequest;
32
+ res: ExpressResponse;
33
+ service: string;
34
+ }): Promise<JSONObject> => {
35
+ const accessToken: string | undefined =
36
+ UserMiddleware.getAccessTokenFromExpressRequest(data.req);
37
+
38
+ if (!accessToken) {
39
+ return {};
40
+ }
41
+
42
+ let authData: JSONWebTokenData;
43
+
44
+ try {
45
+ authData = JSONWebToken.decode(accessToken);
46
+ } catch (error) {
47
+ // Expired or unreadable: let the app load and refresh it.
48
+ logger.debug(error, { service: data.service });
49
+ return {};
50
+ }
51
+
52
+ if (!authData.isMasterAdmin) {
53
+ Response.sendErrorResponse(
54
+ data.req,
55
+ data.res,
56
+ new NotAuthorizedException(NOT_A_MASTER_ADMIN_MESSAGE),
57
+ );
58
+ }
59
+
60
+ return {};
61
+ };
@@ -86,6 +86,7 @@ export default class MonitorAlert {
86
86
  select: {
87
87
  _id: true,
88
88
  title: true,
89
+ createdAt: true,
89
90
  createdCriteriaId: true,
90
91
  projectId: true,
91
92
  alertNumber: true,
@@ -514,6 +515,7 @@ export default class MonitorAlert {
514
515
  relatedAlertNumber: alreadyOpenAlert?.alertNumber,
515
516
  relatedAlertNumberWithPrefix:
516
517
  alreadyOpenAlert?.alertNumberWithPrefix,
518
+ relatedAlertCreatedAt: alreadyOpenAlert?.createdAt,
517
519
  at: OneUptimeDate.getCurrentDate(),
518
520
  });
519
521
  continue;
@@ -794,7 +796,7 @@ export default class MonitorAlert {
794
796
  relatedAlertId: createdAlert.id?.toString(),
795
797
  relatedAlertNumber: createdAlert.alertNumber,
796
798
  relatedAlertNumberWithPrefix: createdAlert.alertNumberWithPrefix,
797
- at: OneUptimeDate.getCurrentDate(),
799
+ at: createdAlert.createdAt || OneUptimeDate.getCurrentDate(),
798
800
  });
799
801
  } catch (err) {
800
802
  /*
@@ -99,6 +99,7 @@ export default class MonitorIncident {
99
99
  select: {
100
100
  _id: true,
101
101
  title: true,
102
+ createdAt: true,
102
103
  createdCriteriaId: true,
103
104
  createdIncidentTemplateId: true,
104
105
  projectId: true,
@@ -579,6 +580,7 @@ export default class MonitorIncident {
579
580
  relatedIncidentNumber: alreadyOpenIncident?.incidentNumber,
580
581
  relatedIncidentNumberWithPrefix:
581
582
  alreadyOpenIncident?.incidentNumberWithPrefix,
583
+ relatedIncidentCreatedAt: alreadyOpenIncident?.createdAt,
582
584
  at: OneUptimeDate.getCurrentDate(),
583
585
  });
584
586
  continue;
@@ -913,7 +915,7 @@ export default class MonitorIncident {
913
915
  relatedIncidentNumber: createdIncident.incidentNumber,
914
916
  relatedIncidentNumberWithPrefix:
915
917
  createdIncident.incidentNumberWithPrefix,
916
- at: OneUptimeDate.getCurrentDate(),
918
+ at: createdIncident.createdAt || OneUptimeDate.getCurrentDate(),
917
919
  });
918
920
  } catch (err) {
919
921
  /*
@@ -176,7 +176,7 @@ export interface EmptyOutcomeOptions {
176
176
  }
177
177
 
178
178
  /* The schedule facts every render needs, read once per request. */
179
- interface ScheduleInfo {
179
+ export interface ScheduleInfo {
180
180
  id: ObjectID;
181
181
  name: string;
182
182
  timezone?: string | undefined;
@@ -24,6 +24,19 @@ import Dictionary from "../../Types/Dictionary";
24
24
  import UserPermissionUtil from "./UserPermission/UserPermission";
25
25
  import CaptureSpan from "./Telemetry/CaptureSpan";
26
26
 
27
+ // What became of one ListenToModelEvent request.
28
+ export enum ListenToModelEventOutcome {
29
+ Joined = "Joined",
30
+ // No access token, or one that no longer decodes. The client was told.
31
+ AuthenticationRequired = "AuthenticationRequired",
32
+ // A valid session without access to this tenant or model.
33
+ NotAuthorized = "NotAuthorized",
34
+ // The request itself was malformed.
35
+ InvalidRequest = "InvalidRequest",
36
+ // Something failed while authorizing (for example the permission cache).
37
+ Failed = "Failed",
38
+ }
39
+
27
40
  export default abstract class Realtime {
28
41
  private static socketServer: SocketServer | null = null;
29
42
 
@@ -45,37 +58,19 @@ export default abstract class Realtime {
45
58
  this.socketServer!.on("connection", (socket: Socket) => {
46
59
  logger.debug("New socket connection established");
47
60
 
48
- socket.on(EventName.ListenToModalEvent, async (data: JSONObject) => {
49
- logger.debug("Received ListenToModalEvent with data:");
50
- logger.debug(data);
51
-
52
- const socketLogAttributes: LogAttributes = {
53
- projectId: data["tenantId"]?.toString(),
54
- };
55
-
56
- if (typeof data["eventType"] !== "string") {
57
- logger.error("eventType is not a string", socketLogAttributes);
58
- throw new BadDataException("eventType is not a string");
59
- }
60
- if (typeof data["modelType"] !== "string") {
61
- logger.error("modelType is not a string", socketLogAttributes);
62
- throw new BadDataException("modelType is not a string");
63
- }
64
- if (typeof data["modelName"] !== "string") {
65
- logger.error("modelName is not a string", socketLogAttributes);
66
- throw new BadDataException("modelName is not a string");
67
- }
68
- if (typeof data["tenantId"] !== "string") {
69
- logger.error("tenantId is not a string", socketLogAttributes);
70
- throw new BadDataException("tenantId is not a string");
71
- }
72
-
73
- await Realtime.listenToModelEvent(socket, {
74
- eventType: data["eventType"] as ModelEventType,
75
- modelType: data["modelType"] as DatabaseType,
76
- modelName: data["modelName"] as string,
77
- tenantId: data["tenantId"] as string,
78
- });
61
+ /*
62
+ * socket.io calls a listener and throws away what it returns. An async
63
+ * listener that throws is therefore an unhandled rejection: nothing
64
+ * goes back to the client, and the subscription it asked for simply
65
+ * never happens. handleListenToModelEventRequest settles every outcome
66
+ * itself; the catch is a backstop, not the error handling.
67
+ */
68
+ socket.on(EventName.ListenToModalEvent, (data: JSONObject): void => {
69
+ Realtime.handleListenToModelEventRequest(socket, data).catch(
70
+ (err: unknown) => {
71
+ logger.error(err);
72
+ },
73
+ );
79
74
  });
80
75
  });
81
76
  }
@@ -83,11 +78,108 @@ export default abstract class Realtime {
83
78
  return this.socketServer;
84
79
  }
85
80
 
81
+ /*
82
+ * One ListenToModelEvent from a client, start to finish. Never throws: a
83
+ * malformed request, a missing or expired access token, a refused
84
+ * subscription and a failing permission lookup each end here as an outcome,
85
+ * so none of them can become an unhandled rejection in the socket listener.
86
+ */
87
+ @CaptureSpan()
88
+ public static async handleListenToModelEventRequest(
89
+ socket: Socket,
90
+ data: JSONObject,
91
+ ): Promise<ListenToModelEventOutcome> {
92
+ logger.debug("Received ListenToModalEvent with data:");
93
+ logger.debug(data);
94
+
95
+ let request: ListenToModelEventJSON;
96
+
97
+ try {
98
+ request = Realtime.parseListenToModelEventRequest(data);
99
+ } catch (err) {
100
+ logger.error(err);
101
+ return ListenToModelEventOutcome.InvalidRequest;
102
+ }
103
+
104
+ try {
105
+ return await Realtime.listenToModelEvent(socket, request);
106
+ } catch (err) {
107
+ // A permission-cache (Redis) failure, say. The room is not joined.
108
+ const failureLogAttributes: LogAttributes = {
109
+ projectId: request.tenantId,
110
+ };
111
+
112
+ logger.error(err, failureLogAttributes);
113
+ return ListenToModelEventOutcome.Failed;
114
+ }
115
+ }
116
+
117
+ private static parseListenToModelEventRequest(
118
+ data: JSONObject,
119
+ ): ListenToModelEventJSON {
120
+ if (!data || typeof data !== "object") {
121
+ logger.error("ListenToModelEvent data is not an object");
122
+ throw new BadDataException("ListenToModelEvent data is not an object");
123
+ }
124
+
125
+ const socketLogAttributes: LogAttributes = {
126
+ projectId: data["tenantId"]?.toString(),
127
+ };
128
+
129
+ if (typeof data["eventType"] !== "string") {
130
+ logger.error("eventType is not a string", socketLogAttributes);
131
+ throw new BadDataException("eventType is not a string");
132
+ }
133
+ if (typeof data["modelType"] !== "string") {
134
+ logger.error("modelType is not a string", socketLogAttributes);
135
+ throw new BadDataException("modelType is not a string");
136
+ }
137
+ if (typeof data["modelName"] !== "string") {
138
+ logger.error("modelName is not a string", socketLogAttributes);
139
+ throw new BadDataException("modelName is not a string");
140
+ }
141
+ if (typeof data["tenantId"] !== "string") {
142
+ logger.error("tenantId is not a string", socketLogAttributes);
143
+ throw new BadDataException("tenantId is not a string");
144
+ }
145
+
146
+ return {
147
+ eventType: data["eventType"] as ModelEventType,
148
+ modelType: data["modelType"] as DatabaseType,
149
+ modelName: data["modelName"] as string,
150
+ tenantId: data["tenantId"] as string,
151
+ };
152
+ }
153
+
154
+ /*
155
+ * The socket has no usable user session: tell the client, which refreshes
156
+ * its session and reconnects so the new handshake carries the new cookie.
157
+ * Dropping the request silently is what used to happen, and it left every
158
+ * subscription made after the access token expired dead (no live counters
159
+ * after switching project, no live logs) with nothing in the browser to
160
+ * show why.
161
+ */
162
+ private static rejectForMissingAuthentication(
163
+ socket: Socket,
164
+ data: ListenToModelEventJSON,
165
+ reason: string,
166
+ listenLogAttributes: LogAttributes,
167
+ ): ListenToModelEventOutcome {
168
+ logger.debug(
169
+ `${reason}, aborting joining room and asking the client to re-authenticate`,
170
+ listenLogAttributes,
171
+ );
172
+
173
+ socket.emit(EventName.AuthenticationRequired, data);
174
+
175
+ return ListenToModelEventOutcome.AuthenticationRequired;
176
+ }
177
+
86
178
  @CaptureSpan()
87
179
  public static async listenToModelEvent(
88
180
  socket: Socket,
89
181
  data: ListenToModelEventJSON,
90
- ): Promise<void> {
182
+ ): Promise<ListenToModelEventOutcome> {
91
183
  const listenLogAttributes: LogAttributes = {
92
184
  projectId: data.tenantId?.toString(),
93
185
  };
@@ -116,31 +208,51 @@ export default abstract class Realtime {
116
208
  this.getAccessTokenFromSocket(socket);
117
209
 
118
210
  if (!userAccessToken) {
119
- logger.debug(
120
- "User access token not found in socket, aborting joining room",
211
+ return this.rejectForMissingAuthentication(
212
+ socket,
213
+ data,
214
+ "User access token not found in socket",
121
215
  listenLogAttributes,
122
216
  );
123
- return;
124
217
  }
125
218
 
126
219
  logger.debug("Decoding user access token", listenLogAttributes);
127
- const userAuthorizationData: JSONWebTokenData =
128
- JSONWebToken.decode(userAccessToken);
220
+
221
+ /*
222
+ * The token is the one the browser sent with the handshake, and it is not
223
+ * re-read for the life of the connection. Once it expires every decode
224
+ * throws, which is the normal state of a dashboard tab left open past the
225
+ * access token's lifetime, not an error in the request.
226
+ */
227
+ let userAuthorizationData: JSONWebTokenData;
228
+
229
+ try {
230
+ userAuthorizationData = JSONWebToken.decode(userAccessToken);
231
+ } catch {
232
+ return this.rejectForMissingAuthentication(
233
+ socket,
234
+ data,
235
+ "User access token in socket is invalid or expired",
236
+ listenLogAttributes,
237
+ );
238
+ }
129
239
 
130
240
  if (!userAuthorizationData) {
131
- logger.debug(
132
- "User authorization data not found in socket, aborting joining room",
241
+ return this.rejectForMissingAuthentication(
242
+ socket,
243
+ data,
244
+ "User authorization data not found in socket",
133
245
  listenLogAttributes,
134
246
  );
135
- return;
136
247
  }
137
248
 
138
249
  if (!userAuthorizationData.userId) {
139
- logger.debug(
140
- "User ID not found in socket, aborting joining room",
250
+ return this.rejectForMissingAuthentication(
251
+ socket,
252
+ data,
253
+ "User ID not found in socket",
141
254
  listenLogAttributes,
142
255
  );
143
- return;
144
256
  }
145
257
 
146
258
  logger.debug("Checking user access permissions", listenLogAttributes);
@@ -179,7 +291,7 @@ export default abstract class Realtime {
179
291
  "User does not have access to this tenant, aborting joining room",
180
292
  listenLogAttributes,
181
293
  );
182
- return;
294
+ return ListenToModelEventOutcome.NotAuthorized;
183
295
  }
184
296
 
185
297
  logger.debug(
@@ -214,12 +326,16 @@ export default abstract class Realtime {
214
326
  }
215
327
  }
216
328
 
329
+ /*
330
+ * Authenticated but not allowed. The room is not joined and, as before,
331
+ * nothing is sent back: a fresh session would not change the answer.
332
+ */
217
333
  if (!hasAccess) {
218
334
  logger.debug(
219
335
  "User does not have access to this tenant, aborting joining room",
220
336
  listenLogAttributes,
221
337
  );
222
- return;
338
+ return ListenToModelEventOutcome.NotAuthorized;
223
339
  }
224
340
 
225
341
  if (data.modelId) {
@@ -244,6 +360,8 @@ export default abstract class Realtime {
244
360
  // join the room.
245
361
  await socket.join(roomId);
246
362
  }
363
+
364
+ return ListenToModelEventOutcome.Joined;
247
365
  }
248
366
 
249
367
  @CaptureSpan()