@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
@@ -12,9 +12,13 @@ import Response from "../../../Server/Utils/Response";
12
12
  import DatabaseCommonInteractionProps from "../../../Types/BaseDatabase/DatabaseCommonInteractionProps";
13
13
  import BadDataException from "../../../Types/Exception/BadDataException";
14
14
  import NotAuthorizedException from "../../../Types/Exception/NotAuthorizedException";
15
+ import NotAuthenticatedException from "../../../Types/Exception/NotAuthenticatedException";
16
+ import Exception from "../../../Types/Exception/Exception";
17
+ import ExceptionCode from "../../../Types/Exception/ExceptionCode";
15
18
  import { ROUTINE_EMAIL_EVENT_TYPES } from "../../../Types/NotificationSetting/RoutineEmailEvents";
16
19
  import ObjectID from "../../../Types/ObjectID";
17
20
  import Permission from "../../../Types/Permission";
21
+ import UserType from "../../../Types/UserType";
18
22
 
19
23
  jest.mock("../../../Server/Utils/Express", () => {
20
24
  return {
@@ -29,6 +33,15 @@ const USER_ID: ObjectID = ObjectID.generate();
29
33
  const PROJECT_ID: ObjectID = ObjectID.generate();
30
34
  const OTHER_PROJECT_ID: ObjectID = ObjectID.generate();
31
35
 
36
+ /*
37
+ * The exception the handler handed to next(). Its code is the HTTP status the
38
+ * client sees, and the browser client refreshes the session on 401 only, so
39
+ * the code is asserted alongside the class.
40
+ */
41
+ function errorPassedTo(next: jest.Mock): Exception {
42
+ return next.mock.calls[0]![0] as Exception;
43
+ }
44
+
32
45
  describe("POST reduce routine emails", () => {
33
46
  let props: DatabaseCommonInteractionProps;
34
47
  let reduceSpy: jest.SpyInstance;
@@ -128,21 +141,67 @@ describe("POST reduce routine emails", () => {
128
141
  });
129
142
  });
130
143
 
131
- test.each(["anonymous", "project API key"])(
132
- "rejects a %s without an authenticated user",
133
- async () => {
144
+ /*
145
+ * Both callers are refused, but differently. The anonymous one - no user, no
146
+ * key, typically a dashboard tab whose access-token cookie expired - gets
147
+ * NotAuthenticatedException (401), which is what makes the browser refresh
148
+ * the session and resend; it used to get the 422 below. A project API key
149
+ * is authenticated but is nobody's preferences, so it keeps the 422: a 401
150
+ * would send its client off to refresh a session it never had.
151
+ */
152
+ test.each([
153
+ {
154
+ caller: "an anonymous caller",
155
+ userType: undefined,
156
+ exception: NotAuthenticatedException,
157
+ code: ExceptionCode.NotAuthenticatedException,
158
+ },
159
+ {
160
+ caller: "an explicitly Public caller",
161
+ userType: UserType.Public,
162
+ exception: NotAuthenticatedException,
163
+ code: ExceptionCode.NotAuthenticatedException,
164
+ },
165
+ {
166
+ caller: "a project API key",
167
+ userType: UserType.API,
168
+ exception: NotAuthorizedException,
169
+ code: ExceptionCode.NotAuthorizedException,
170
+ },
171
+ ])(
172
+ "rejects $caller without an authenticated user",
173
+ async (testCase: {
174
+ caller: string;
175
+ userType: UserType | undefined;
176
+ exception:
177
+ | typeof NotAuthenticatedException
178
+ | typeof NotAuthorizedException;
179
+ code: ExceptionCode;
180
+ }) => {
134
181
  props.userId = undefined;
182
+ props.userType = testCase.userType;
135
183
  const next: jest.Mock = await call({ userId: USER_ID.toString() });
136
- expect(next).toHaveBeenCalledWith(expect.any(NotAuthorizedException));
184
+ expect(next).toHaveBeenCalledWith(expect.any(testCase.exception));
185
+ expect(errorPassedTo(next).code).toBe(testCase.code);
137
186
  expect(reduceSpy).not.toHaveBeenCalled();
138
187
  expect(responseSpy).not.toHaveBeenCalled();
139
188
  },
140
189
  );
141
190
 
191
+ test("an anonymous caller with no tenant is asked to log in before the missing project is reported", async () => {
192
+ props.userId = undefined;
193
+ props.tenantId = undefined;
194
+ const next: jest.Mock = await call();
195
+ expect(next).toHaveBeenCalledWith(expect.any(NotAuthenticatedException));
196
+ expect(errorPassedTo(next).code).toBe(401);
197
+ expect(reduceSpy).not.toHaveBeenCalled();
198
+ });
199
+
142
200
  test("rejects missing project context before changing preferences", async () => {
143
201
  props.tenantId = undefined;
144
202
  const next: jest.Mock = await call({ projectId: PROJECT_ID.toString() });
145
203
  expect(next).toHaveBeenCalledWith(expect.any(BadDataException));
204
+ expect(errorPassedTo(next).code).toBe(ExceptionCode.BadDataException);
146
205
  expect(reduceSpy).not.toHaveBeenCalled();
147
206
  });
148
207
 
@@ -150,6 +209,7 @@ describe("POST reduce routine emails", () => {
150
209
  props.userTenantAccessPermission = undefined;
151
210
  const next: jest.Mock = await call();
152
211
  expect(next).toHaveBeenCalledWith(expect.any(NotAuthorizedException));
212
+ expect(errorPassedTo(next).code).toBe(ExceptionCode.NotAuthorizedException);
153
213
  expect(reduceSpy).not.toHaveBeenCalled();
154
214
  });
155
215
 
@@ -157,6 +217,7 @@ describe("POST reduce routine emails", () => {
157
217
  props.tenantId = OTHER_PROJECT_ID;
158
218
  const next: jest.Mock = await call();
159
219
  expect(next).toHaveBeenCalledWith(expect.any(NotAuthorizedException));
220
+ expect(errorPassedTo(next).code).toBe(ExceptionCode.NotAuthorizedException);
160
221
  expect(reduceSpy).not.toHaveBeenCalled();
161
222
  });
162
223
 
@@ -18,6 +18,10 @@ import TeamMember from "../../../Models/DatabaseModels/TeamMember";
18
18
  import DatabaseCommonInteractionProps from "../../../Types/BaseDatabase/DatabaseCommonInteractionProps";
19
19
  import { DEFAULT_LIMIT } from "../../../Types/Database/LimitMax";
20
20
  import Dictionary from "../../../Types/Dictionary";
21
+ import BadDataException from "../../../Types/Exception/BadDataException";
22
+ import Exception from "../../../Types/Exception/Exception";
23
+ import ExceptionCode from "../../../Types/Exception/ExceptionCode";
24
+ import NotAuthenticatedException from "../../../Types/Exception/NotAuthenticatedException";
21
25
  import NotAuthorizedException from "../../../Types/Exception/NotAuthorizedException";
22
26
  import { JSONObject } from "../../../Types/JSON";
23
27
  import JSONWebTokenData from "../../../Types/JsonWebTokenData";
@@ -916,7 +920,7 @@ describe("POST /user/:userId/projects — the master API key path", () => {
916
920
  type MiddlewareCallResult = {
917
921
  // Whether the gate let the request through to the read.
918
922
  reachedHandler: boolean;
919
- errorSentToClient: NotAuthorizedException | undefined;
923
+ errorSentToClient: Exception | undefined;
920
924
  // The request object as the handler saw it, to inspect what the gate set.
921
925
  request: ExpressRequest;
922
926
  };
@@ -974,7 +978,7 @@ describe("POST /user/:userId/projects — the master API key path", () => {
974
978
 
975
979
  return {
976
980
  reachedHandler: reachedHandler,
977
- errorSentToClient: errorCall?.[2] as NotAuthorizedException | undefined,
981
+ errorSentToClient: errorCall?.[2] as Exception | undefined,
978
982
  request: req,
979
983
  };
980
984
  }
@@ -1145,7 +1149,19 @@ describe("POST /user/:userId/projects — the master API key path", () => {
1145
1149
  expect(findBySpy).not.toHaveBeenCalled();
1146
1150
  expect(Response.sendJsonArrayResponse).not.toHaveBeenCalled();
1147
1151
 
1148
- expect(result.errorSentToClient).toBeInstanceOf(NotAuthorizedException);
1152
+ /*
1153
+ * An unusable key falls through to the session check, and with no
1154
+ * session that is the no-token refusal - a 401 now, where it used to
1155
+ * be a NotAuthorizedException (422). Still a refusal, and still AT the
1156
+ * gate; only the status changed, so that an Admin Dashboard tab whose
1157
+ * session cookie has expired refreshes instead of showing an error.
1158
+ */
1159
+ expect(result.errorSentToClient).toBeInstanceOf(
1160
+ NotAuthenticatedException,
1161
+ );
1162
+ expect(result.errorSentToClient?.code).toBe(
1163
+ ExceptionCode.NotAuthenticatedException,
1164
+ );
1149
1165
  expect(result.errorSentToClient?.message).toBe(
1150
1166
  "Unauthorized: Access token is required.",
1151
1167
  );
@@ -1159,6 +1175,41 @@ describe("POST /user/:userId/projects — the master API key path", () => {
1159
1175
 
1160
1176
  expect(result.reachedHandler).toBe(false);
1161
1177
  expect(findBySpy).not.toHaveBeenCalled();
1178
+
1179
+ /*
1180
+ * This is what the Admin Dashboard's User > Projects page sends once
1181
+ * its session cookie has expired. Only a 401 makes the browser client
1182
+ * refresh the session and replay the read.
1183
+ */
1184
+ expect(result.errorSentToClient).toBeInstanceOf(
1185
+ NotAuthenticatedException,
1186
+ );
1187
+ expect(result.errorSentToClient?.code).toBe(
1188
+ ExceptionCode.NotAuthenticatedException,
1189
+ );
1190
+ });
1191
+
1192
+ test("refuses an expired session with no key with a 401, without reading anything", async () => {
1193
+ jest
1194
+ .spyOn(UserMiddleware, "getAccessTokenFromExpressRequest")
1195
+ .mockReturnValue("an.expired.token" as never);
1196
+
1197
+ jest.spyOn(JSONWebToken, "decode").mockImplementation(() => {
1198
+ throw new BadDataException("AccessToken is invalid or expired");
1199
+ });
1200
+
1201
+ const result: MiddlewareCallResult = await callThroughMiddleware({
1202
+ headers: {},
1203
+ });
1204
+
1205
+ expect(result.reachedHandler).toBe(false);
1206
+ expect(findBySpy).not.toHaveBeenCalled();
1207
+ expect(result.errorSentToClient).toBeInstanceOf(
1208
+ NotAuthenticatedException,
1209
+ );
1210
+ expect(result.errorSentToClient?.message).toBe(
1211
+ "Unauthorized: Invalid or expired access token.",
1212
+ );
1162
1213
  });
1163
1214
 
1164
1215
  /*
@@ -1231,6 +1282,15 @@ describe("POST /user/:userId/projects — the master API key path", () => {
1231
1282
  expect(result.errorSentToClient?.message).toBe(
1232
1283
  "Unauthorized: Only master admins can perform this action.",
1233
1284
  );
1285
+
1286
+ /*
1287
+ * Still a 422, unlike the missing-token case: this caller is signed in,
1288
+ * and refreshing their session would not make them a master admin.
1289
+ */
1290
+ expect(result.errorSentToClient).toBeInstanceOf(NotAuthorizedException);
1291
+ expect(result.errorSentToClient?.code).toBe(
1292
+ ExceptionCode.NotAuthorizedException,
1293
+ );
1234
1294
  });
1235
1295
 
1236
1296
  /*
@@ -1,4 +1,5 @@
1
1
  import UserTotpAuthAPI from "../../../Server/API/UserTotpAuthAPI";
2
+ import UserMiddleware from "../../../Server/Middleware/UserAuthorization";
2
3
  import UserTotpAuthService from "../../../Server/Services/UserTotpAuthService";
3
4
  import UserService from "../../../Server/Services/UserService";
4
5
  import UserTwoFactorBackupCodeService from "../../../Server/Services/UserTwoFactorBackupCodeService";
@@ -17,6 +18,8 @@ import Dictionary from "../../../Types/Dictionary";
17
18
  import Email from "../../../Types/Email";
18
19
  import BadDataException from "../../../Types/Exception/BadDataException";
19
20
  import Exception from "../../../Types/Exception/Exception";
21
+ import ExceptionCode from "../../../Types/Exception/ExceptionCode";
22
+ import NotAuthenticatedException from "../../../Types/Exception/NotAuthenticatedException";
20
23
  import { JSONObject } from "../../../Types/JSON";
21
24
  import ObjectID from "../../../Types/ObjectID";
22
25
  import UserTotpAuth from "../../../Models/DatabaseModels/UserTotpAuth";
@@ -358,11 +361,54 @@ describe("POST /user-totp-auth/validate", () => {
358
361
  * `userAuthorization` off an unauthenticated request, the ownership
359
362
  * comparison below would compare against `undefined`, and anybody could
360
363
  * verify anybody's TOTP row.
364
+ *
365
+ * Two middlewares now, asserted by identity (a count of two would not
366
+ * notice one being swapped for another). getUserMiddleware resolves the
367
+ * session, but lets a request with NO session through as Public;
368
+ * requireUserAuthentication is what turns that request into a 401. It was
369
+ * added because an enrolment page left open past the session lifetime
370
+ * sends exactly that request - the access-token cookie expires with the
371
+ * token - and the handler answered it with a "Two factor auth not found"
372
+ * 400 (after reading the row as root), which the browser client does not
373
+ * treat as a cue to refresh the session and retry.
361
374
  */
362
375
  test("is behind an authentication middleware", () => {
363
- expect(mockRouter.match("post", VALIDATE_ROUTE).middlewares.length).toBe(
364
- 1,
376
+ expect(mockRouter.match("post", VALIDATE_ROUTE).middlewares).toEqual([
377
+ UserMiddleware.getUserMiddleware,
378
+ UserMiddleware.requireUserAuthentication,
379
+ ]);
380
+ });
381
+
382
+ test("answers a request with no session 401 before any row is read", async () => {
383
+ const req: OneUptimeRequest = {
384
+ body: { id: TOTP_ID.toString(), code: "123456" },
385
+ params: {},
386
+ query: {},
387
+ headers: {},
388
+ } as unknown as OneUptimeRequest;
389
+
390
+ const res: OneUptimeResponse = {
391
+ status: jest.fn().mockReturnThis(),
392
+ } as unknown as OneUptimeResponse;
393
+
394
+ const next: jest.Mock = jest.fn();
395
+
396
+ await mockRouter.match("post", VALIDATE_ROUTE).middlewares[1]!(
397
+ req,
398
+ res,
399
+ next as unknown as NextFunction,
365
400
  );
401
+
402
+ expect(next).not.toHaveBeenCalled();
403
+
404
+ const error: Exception = asMock(Response.sendErrorResponse).mock
405
+ .calls[0]![2] as Exception;
406
+
407
+ expect(error).toBeInstanceOf(NotAuthenticatedException);
408
+ expect(error.code).toBe(ExceptionCode.NotAuthenticatedException);
409
+ expect(findTotpById).not.toHaveBeenCalled();
410
+ expect(updateTotpById).not.toHaveBeenCalled();
411
+ expect(generateForUserIfNoneSpy).not.toHaveBeenCalled();
366
412
  });
367
413
  });
368
414
 
@@ -281,20 +281,29 @@ describe("POST /user-webauthn/generate-authentication-options", () => {
281
281
  ["registration options", REGISTRATION_OPTIONS_ROUTE],
282
282
  ["verify registration", VERIFY_REGISTRATION_ROUTE],
283
283
  ])(
284
- "%s stays behind the user middleware alone",
284
+ "%s stays behind the user middleware and its authentication guard alone",
285
285
  (_name: string, uri: string) => {
286
286
  /*
287
287
  * Both are authenticated, and neither carries an email in its body --
288
288
  * so the limiter's account key would collapse to the same value for
289
289
  * every caller and one user's enrolment attempts would throttle
290
290
  * everybody's.
291
+ *
292
+ * The second entry is requireUserAuthentication, not a limiter. It
293
+ * turns a request with no session (the access-token cookie expired
294
+ * while the enrolment dialog was open) into a 401 the browser client
295
+ * refreshes on. It is the only thing allowed after getUserMiddleware.
291
296
  */
292
297
  const route: { middlewares: Array<unknown> } = mockRouter.match(
293
298
  "post",
294
299
  uri,
295
300
  );
296
301
 
297
- expect(route.middlewares).toEqual([UserMiddleware.getUserMiddleware]);
302
+ expect(route.middlewares).toEqual([
303
+ UserMiddleware.getUserMiddleware,
304
+ UserMiddleware.requireUserAuthentication,
305
+ ]);
306
+ expect(route.middlewares).not.toContain(mountedMiddleware);
298
307
  },
299
308
  );
300
309
  });
@@ -13,6 +13,9 @@ import { mockRouter } from "./Helpers";
13
13
  import { getJestSpyOn } from "../../Spy";
14
14
  import Dictionary from "../../../Types/Dictionary";
15
15
  import BadDataException from "../../../Types/Exception/BadDataException";
16
+ import Exception from "../../../Types/Exception/Exception";
17
+ import ExceptionCode from "../../../Types/Exception/ExceptionCode";
18
+ import NotAuthenticatedException from "../../../Types/Exception/NotAuthenticatedException";
16
19
  import { JSONObject } from "../../../Types/JSON";
17
20
  import ObjectID from "../../../Types/ObjectID";
18
21
  import {
@@ -336,20 +339,60 @@ afterEach(() => {
336
339
 
337
340
  describe("POST /user-webauthn/verify-registration", () => {
338
341
  describe("the route itself", () => {
339
- test("is registered as a POST behind the user middleware", () => {
342
+ test("is registered as a POST behind the user middleware and the authentication guard", () => {
340
343
  /*
341
344
  * The handler takes the owning user from `userAuthorization`, which is
342
345
  * put on the request by this middleware and by nothing else. Without it
343
346
  * the id would be undefined for every caller, and asserted by IDENTITY
344
347
  * rather than by counting because swapping in a different middleware
345
- * keeps the count at one.
348
+ * keeps the count the same.
349
+ *
350
+ * getUserMiddleware lets a request with NO session through as Public,
351
+ * so requireUserAuthentication follows it and answers that request with
352
+ * a 401. A key-enrolment dialog left open until the access-token cookie
353
+ * expired sends exactly that request, and only a 401 makes the browser
354
+ * client refresh the session and replay the registration.
346
355
  */
347
356
  const route: { middlewares: Array<unknown> } = mockRouter.match(
348
357
  "post",
349
358
  VERIFY_REGISTRATION_ROUTE,
350
359
  );
351
360
 
352
- expect(route.middlewares).toEqual([UserMiddleware.getUserMiddleware]);
361
+ expect(route.middlewares).toEqual([
362
+ UserMiddleware.getUserMiddleware,
363
+ UserMiddleware.requireUserAuthentication,
364
+ ]);
365
+ });
366
+
367
+ test("answers a request with no session 401 before registering or minting anything", async () => {
368
+ const req: OneUptimeRequest = {
369
+ params: {},
370
+ query: {},
371
+ body: { credential: CREDENTIAL_FROM_THE_BROWSER, name: KEY_NAME },
372
+ headers: {},
373
+ } as unknown as OneUptimeRequest;
374
+
375
+ const res: OneUptimeResponse = {
376
+ status: jest.fn().mockReturnThis(),
377
+ } as unknown as OneUptimeResponse;
378
+
379
+ const next: jest.Mock = jest.fn();
380
+
381
+ await mockRouter.match("post", VERIFY_REGISTRATION_ROUTE).middlewares[1]!(
382
+ req,
383
+ res,
384
+ next as unknown as NextFunction,
385
+ );
386
+
387
+ expect(next).not.toHaveBeenCalled();
388
+
389
+ const error: Exception = asMock(Response.sendErrorResponse).mock
390
+ .calls[0]![2] as Exception;
391
+
392
+ expect(error).toBeInstanceOf(NotAuthenticatedException);
393
+ expect(error.code).toBe(ExceptionCode.NotAuthenticatedException);
394
+ expect(verifyRegistrationSpy).not.toHaveBeenCalled();
395
+ expect(mintSpy).not.toHaveBeenCalled();
353
396
  });
354
397
 
355
398
  test("carries no route parameter that could name a user", () => {
@@ -27,7 +27,13 @@ jest.mock("../../../Server/API/CommonAPI", () => {
27
27
  });
28
28
 
29
29
  jest.mock("../../../Server/Middleware/UserAuthorization", () => {
30
- return { __esModule: true, default: { getUserMiddleware: jest.fn() } };
30
+ return {
31
+ __esModule: true,
32
+ default: {
33
+ getUserMiddleware: jest.fn(),
34
+ requireUserAuthentication: jest.fn(),
35
+ },
36
+ };
31
37
  });
32
38
 
33
39
  jest.mock("../../../Server/Middleware/IdentityRateLimit", () => {
@@ -107,9 +113,19 @@ describe("passkey registration API", () => {
107
113
  jest.restoreAllMocks();
108
114
  });
109
115
 
116
+ /*
117
+ * getUserMiddleware resolves the session; requireUserAuthentication turns a
118
+ * request that has none (a settings page left open until the access-token
119
+ * cookie expired) into a 401 the browser client refreshes on, rather than
120
+ * letting the handler dereference a missing userAuthorization. Both are
121
+ * mocked to distinct functions so the identity check below is real: with
122
+ * the second left out of the mock, the route would register `undefined` in
123
+ * its place and toEqual would still match a one-element list.
124
+ */
110
125
  test("requires authentication before allowing registration", () => {
111
- expect(mockRouter.match("post", ROUTE).middlewares).toEqual([
126
+ expect(mockRouter.match("post", ROUTE).middlewares).toStrictEqual([
112
127
  UserMiddleware.getUserMiddleware,
128
+ UserMiddleware.requireUserAuthentication,
113
129
  ]);
114
130
  });
115
131
 
@@ -1,4 +1,4 @@
1
- import { describe, expect, test } from "@jest/globals";
1
+ import { beforeAll, describe, expect, test } from "@jest/globals";
2
2
  import express from "express";
3
3
  import http from "http";
4
4
  import { AddressInfo } from "net";
@@ -118,11 +118,21 @@ const httpGetJson: HttpGetJsonFunction = (data: {
118
118
  };
119
119
 
120
120
  describe("ANON ACCESS PROBE /microsoft-teams/chats", () => {
121
- test("unauthenticated GET with only a tenantid header", async () => {
122
- const MicrosoftTeamsAPI: any = (
123
- await import("../../../Server/API/MicrosoftTeamsAPI")
124
- ).default;
121
+ let MicrosoftTeamsAPI: any = undefined;
122
+
123
+ /*
124
+ * Loading MicrosoftTeamsAPI pulls in a large module graph. Done inside the
125
+ * test, that load counted against the probe's 30s budget and timed the test
126
+ * out on a busy machine even though the route answered correctly. The load
127
+ * gets its own, generous budget here so the test's timeout measures only the
128
+ * HTTP round trip it is about.
129
+ */
130
+ beforeAll(async () => {
131
+ MicrosoftTeamsAPI = (await import("../../../Server/API/MicrosoftTeamsAPI"))
132
+ .default;
133
+ }, 600000);
125
134
 
135
+ test("unauthenticated GET with only a tenantid header", async () => {
126
136
  const app: express.Express = express();
127
137
  app.use("/api", new MicrosoftTeamsAPI().getRouter());
128
138
 
@@ -148,9 +158,16 @@ describe("ANON ACCESS PROBE /microsoft-teams/chats", () => {
148
158
  * route must reject one carrying only a tenantid header. A 200 here would
149
159
  * mean the captured chat list leaks to anonymous callers - the exact
150
160
  * regression this probe guards against.
161
+ *
162
+ * Pinned to exactly 401 (it used to accept any 4xx, and was a 422). A
163
+ * request with only a tenantid header is what a signed-in user's browser
164
+ * sends once the access-token cookie has expired, and the dashboard
165
+ * refreshes the session and resends on a 401 and on nothing else.
151
166
  */
152
- expect(result.status).toBeGreaterThanOrEqual(400);
153
- expect(result.status).toBeLessThan(500);
167
+ expect(result.status).toBe(401);
168
+ expect((result.body as { message?: string }).message).toBe(
169
+ "Authentication required. Please log in to access this resource.",
170
+ );
154
171
 
155
172
  const serializedBody: string = JSON.stringify(result.body);
156
173
  expect(serializedBody).not.toContain("Jane Doe");