@oneuptime/common 13.0.7 → 13.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (463) hide show
  1. package/Models/DatabaseModels/OnCallDutyPolicyScheduleCalendarFeed.ts +1 -1
  2. package/Models/DatabaseModels/ProjectOnCallCalendarFeed.ts +1 -1
  3. package/Models/DatabaseModels/UserOnCallCalendarFeed.ts +1 -1
  4. package/Server/API/AIBillingAPI.ts +1 -0
  5. package/Server/API/AIInsightAPI.ts +1 -4
  6. package/Server/API/AIInvestigationAPI.ts +1 -4
  7. package/Server/API/AIReadinessAPI.ts +4 -5
  8. package/Server/API/AlertAPI.ts +1 -0
  9. package/Server/API/AutoRemediationAPI.ts +1 -4
  10. package/Server/API/BaseAPI.ts +13 -0
  11. package/Server/API/BaseAnalyticsAPI.ts +80 -9
  12. package/Server/API/BillingAPI.ts +2 -0
  13. package/Server/API/BillingInvoiceAPI.ts +1 -0
  14. package/Server/API/BillingPaymentMethodAPI.ts +2 -0
  15. package/Server/API/CodeFixRunAPI.ts +1 -3
  16. package/Server/API/CommonAPI.ts +68 -4
  17. package/Server/API/DashboardAPI.ts +12 -12
  18. package/Server/API/GlobalConfigAPI.ts +17 -0
  19. package/Server/API/IncidentAPI.ts +2 -0
  20. package/Server/API/IncidentEpisodeAPI.ts +1 -0
  21. package/Server/API/NotificationAPI.ts +1 -0
  22. package/Server/API/OnCallCalendarAPI.ts +4 -5
  23. package/Server/API/OnCallDutyPolicyAPI.ts +7 -0
  24. package/Server/API/OnCallReadinessAPI.ts +4 -1
  25. package/Server/API/OnCallScheduleTimelineAPI.ts +731 -0
  26. package/Server/API/ProjectAPI.ts +1 -0
  27. package/Server/API/ScheduledMaintenanceAPI.ts +1 -0
  28. package/Server/API/StatusPageAPI.ts +161 -32
  29. package/Server/API/TeamMemberAPI.ts +3 -0
  30. package/Server/API/UserCallAPI.ts +2 -0
  31. package/Server/API/UserEmailAPI.ts +2 -0
  32. package/Server/API/UserIncomingCallNumberAPI.ts +2 -0
  33. package/Server/API/UserMicrosoftTeamsAPI.ts +1 -0
  34. package/Server/API/UserSlackAPI.ts +1 -0
  35. package/Server/API/UserSmsAPI.ts +2 -0
  36. package/Server/API/UserTotpAuthAPI.ts +1 -0
  37. package/Server/API/UserWebAuthnAPI.ts +2 -0
  38. package/Server/API/UserWebhookAPI.ts +1 -0
  39. package/Server/API/UserWhatsAppAPI.ts +2 -0
  40. package/Server/Middleware/MasterAdminAuthorization.ts +13 -2
  41. package/Server/Middleware/UserAuthorization.ts +79 -5
  42. package/Server/Services/ApiKeyPermissionService.ts +101 -4
  43. package/Server/Services/DatabaseService.ts +245 -0
  44. package/Server/Services/DetectionRuleService.ts +5 -4
  45. package/Server/Services/OnCallDutyPolicyChildService.ts +261 -0
  46. package/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.ts +2 -2
  47. package/Server/Services/OnCallDutyPolicyEscalationRuleService.ts +2 -2
  48. package/Server/Services/OnCallDutyPolicyEscalationRuleTeamService.ts +2 -2
  49. package/Server/Services/OnCallDutyPolicyEscalationRuleUserService.ts +2 -2
  50. package/Server/Services/PayAsYouGoBillingService.ts +23 -28
  51. package/Server/Services/ProjectService.ts +18 -0
  52. package/Server/Services/RumSessionPinService.ts +274 -22
  53. package/Server/Services/TeamPermissionService.ts +120 -26
  54. package/Server/Services/ThreatIntelFeedService.ts +6 -3
  55. package/Server/Types/Database/Permissions/BasePermission.ts +9 -7
  56. package/Server/Types/Database/Permissions/Index.ts +75 -11
  57. package/Server/Types/Database/Permissions/TablePermission.ts +24 -28
  58. package/Server/Utils/AI/AIChatPrivacyFilter.ts +8 -0
  59. package/Server/Utils/AI/AIRunPrivacyFilter.ts +8 -0
  60. package/Server/Utils/MasterAdminPageAccess.ts +61 -0
  61. package/Server/Utils/Monitor/MonitorAlert.ts +3 -1
  62. package/Server/Utils/Monitor/MonitorIncident.ts +3 -1
  63. package/Server/Utils/OnCall/OnCallCalendarFeedRenderer.ts +1 -1
  64. package/Server/Utils/Realtime.ts +163 -45
  65. package/Server/Utils/SecurityEvent/DetectionRuleEvaluator.ts +11 -28
  66. package/Server/Utils/SecurityEvent/GoogleSecOpsSeverityRepair.ts +170 -0
  67. package/Server/Utils/SecurityEvent/Sigma/SigmaClickhouseCompiler.ts +1 -1
  68. package/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelFeedPoller.ts +6 -2
  69. package/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelMatcher.ts +10 -9
  70. package/Tests/App/Dashboard/AffectedResourcesPicker.test.tsx +1059 -0
  71. package/Tests/App/Dashboard/AffectedResourcesPickerEditForm.test.tsx +376 -0
  72. package/Tests/App/Dashboard/AffectedResourcesPickerHiddenTypes.test.tsx +757 -0
  73. package/Tests/App/Dashboard/AffectedResourcesSummaryStep.test.tsx +307 -0
  74. package/Tests/App/Dashboard/ArgumentsFormGroupByUnlistedAttributes.test.tsx +131 -0
  75. package/Tests/App/Dashboard/DashboardHeaderRequests.test.tsx +1 -1
  76. package/Tests/App/Dashboard/DashboardMonitorLabelVariable.test.tsx +9 -1
  77. package/Tests/App/Dashboard/DashboardVariableAllContract.test.tsx +24 -0
  78. package/Tests/App/Dashboard/DashboardVariableSelector.test.tsx +162 -8
  79. package/Tests/App/Dashboard/EntityFilterDropdownArchivedSlos.test.tsx +105 -6
  80. package/Tests/App/Dashboard/EntityFilterDropdownUnlistedSelection.test.tsx +434 -0
  81. package/Tests/App/Dashboard/EscalationRuleReadiness.test.tsx +276 -1
  82. package/Tests/App/Dashboard/OnCallCalendarFeedSideMenus.test.tsx +9 -1
  83. package/Tests/App/Dashboard/PayAsYouGoConsentGate.test.tsx +58 -42
  84. package/Tests/App/Dashboard/PayAsYouGoNotices.test.tsx +42 -5
  85. package/Tests/App/Dashboard/ResourceAuditLogsSideMenus.test.tsx +34 -23
  86. package/Tests/App/Dashboard/ScheduleTimeline.test.tsx +1580 -0
  87. package/Tests/App/Dashboard/ScheduleTimelineAPI.test.ts +280 -0
  88. package/Tests/App/Dashboard/ScheduleTimelineModel.test.ts +673 -0
  89. package/Tests/App/Dashboard/SecurityEventConnectionDiagnostics.test.tsx +95 -68
  90. package/Tests/App/Dashboard/SecurityEventsDetectionRulesPage.test.tsx +86 -3
  91. package/Tests/App/Dashboard/SecurityEventsEmptyState.test.tsx +28 -3
  92. package/Tests/App/Dashboard/SecurityEventsExplorer.test.tsx +761 -0
  93. package/Tests/App/Dashboard/SecurityEventsGuideContent.test.ts +1313 -0
  94. package/Tests/App/Dashboard/SecurityEventsHowItWorksCard.test.tsx +536 -0
  95. package/Tests/App/Dashboard/SecurityEventsNoResults.test.tsx +222 -0
  96. package/Tests/App/Dashboard/SecurityEventsThreatIntelPage.test.tsx +199 -0
  97. package/Tests/App/Dashboard/SecurityEventsVolumeChart.test.tsx +321 -0
  98. package/Tests/App/Dashboard/SloOverviewHero.test.tsx +171 -36
  99. package/Tests/App/Dashboard/SloViewSideMenu.test.tsx +215 -0
  100. package/Tests/App/Dashboard/SloViewSideMenuCounts.test.tsx +40 -3
  101. package/Tests/App/PublicDashboard/DashboardVariableSelector.test.tsx +12 -4
  102. package/Tests/App/PublicDashboard/PublicDashboardWidgetListAuth.test.tsx +623 -0
  103. package/Tests/Models/OnCallCalendarFeedModels.test.ts +23 -1
  104. package/Tests/Server/API/AIChatRouteAuthorization.test.ts +138 -5
  105. package/Tests/Server/API/AIGenerationProjectAIToggle.test.ts +187 -0
  106. package/Tests/Server/API/AIInvestigationAvailabilityAuthorization.test.ts +51 -3
  107. package/Tests/Server/API/AIInvestigationEvidenceAPI.test.ts +55 -2
  108. package/Tests/Server/API/BaseAnalyticsAPIAggregateCache.test.ts +729 -0
  109. package/Tests/Server/API/BillingPayAsYouGoStatus.test.ts +93 -7
  110. package/Tests/Server/API/BillingPaymentMethodAPI.test.ts +36 -3
  111. package/Tests/Server/API/CommonAPIAuthGuard.test.ts +1003 -24
  112. package/Tests/Server/API/DashboardPublicRateLimit.test.ts +6 -3
  113. package/Tests/Server/API/ExpiredSessionAIRoutes.test.ts +708 -0
  114. package/Tests/Server/API/ExpiredSessionCustomRoutes.test.ts +928 -0
  115. package/Tests/Server/API/ExpiredSessionMonitorTemplate.test.ts +319 -0
  116. package/Tests/Server/API/ExpiredSessionOnCallDutyPolicy.test.ts +336 -0
  117. package/Tests/Server/API/ExpiredSessionRouteGuards.test.ts +820 -0
  118. package/Tests/Server/API/GlobalConfigLicense.test.ts +140 -0
  119. package/Tests/Server/API/NotificationChannelVerificationAPI.test.ts +115 -12
  120. package/Tests/Server/API/OnCallCalendarAPI.test.ts +375 -8
  121. package/Tests/Server/API/OnCallReadinessAPI.test.ts +175 -17
  122. package/Tests/Server/API/OnCallScheduleTimelineAPI.test.ts +1513 -0
  123. package/Tests/Server/API/OnCallSetupReminderAPI.test.ts +119 -7
  124. package/Tests/Server/API/ProjectScopedCustomRouteAuth.test.ts +111 -4
  125. package/Tests/Server/API/PublicRouteInvalidAccessToken.test.ts +615 -0
  126. package/Tests/Server/API/SecurityEventAttributesAPI.test.ts +89 -2
  127. package/Tests/Server/API/SessionReplayAPI.test.ts +121 -0
  128. package/Tests/Server/API/StatusPageMasterPasswordRateLimit.test.ts +4 -2
  129. package/Tests/Server/API/StatusPagePostmortemVisibility.test.ts +441 -0
  130. package/Tests/Server/API/StatusPageTestEmailReportAuth.test.ts +664 -0
  131. package/Tests/Server/API/TeamMemberRemoveUserFromProjectAPI.test.ts +7 -0
  132. package/Tests/Server/API/UserIncomingCallNumberApi.test.ts +6 -0
  133. package/Tests/Server/API/UserNotificationSettingAPI.test.ts +65 -4
  134. package/Tests/Server/API/UserProjectsAPI.test.ts +63 -3
  135. package/Tests/Server/API/UserTotpAuthAPI.test.ts +48 -2
  136. package/Tests/Server/API/UserWebAuthnAuthenticationOptionsRoute.test.ts +11 -2
  137. package/Tests/Server/API/UserWebAuthnBackupCodeMinting.test.ts +46 -3
  138. package/Tests/Server/API/UserWebAuthnPasskeyAPI.test.ts +18 -2
  139. package/Tests/Server/API/ZZVerifyChatsAuth.test.ts +24 -7
  140. package/Tests/Server/Middleware/ExpiredSessionUserMiddleware.test.ts +563 -0
  141. package/Tests/Server/Middleware/MasterAdminAuthorization.test.ts +299 -19
  142. package/Tests/Server/Middleware/PublicRouteUserMiddleware.test.ts +453 -0
  143. package/Tests/Server/Services/AIChatPrivacyPin.test.ts +24 -0
  144. package/Tests/Server/Services/ApiKeyPermissionSecurity.test.ts +2 -0
  145. package/Tests/Server/Services/ApiKeyPermissionService.test.ts +3 -3
  146. package/Tests/Server/Services/DatabaseServiceCreateSuppliedId.test.ts +147 -0
  147. package/Tests/Server/Services/DatabaseServiceLoginBeforeHooks.test.ts +1078 -0
  148. package/Tests/Server/Services/DatabaseServiceTenantRelationGuard.test.ts +259 -0
  149. package/Tests/Server/Services/DatabaseServiceWriteOperatorValues.test.ts +147 -0
  150. package/Tests/Server/Services/MonitorPayAsYouGoBilling.test.ts +115 -1
  151. package/Tests/Server/Services/OnCallChildCreateAuthorizationPostgres.test.ts +711 -0
  152. package/Tests/Server/Services/OnCallDutyPolicyChildService.test.ts +733 -0
  153. package/Tests/Server/Services/PayAsYouGoBillingService.test.ts +190 -140
  154. package/Tests/Server/Services/PayAsYouGoStripeRateLimitBudget.test.ts +4 -9
  155. package/Tests/Server/Services/PermissionBlockDeletion.test.ts +780 -0
  156. package/Tests/Server/Services/PermissionBlockDeletionPostgres.test.ts +628 -0
  157. package/Tests/Server/Services/ProjectServiceCreateSubscriptionStarted.test.ts +77 -1
  158. package/Tests/Server/Services/RumSessionPinCreatePermission.test.ts +715 -0
  159. package/Tests/Server/Services/TeamMemberMultiTenantReadPostgres.test.ts +394 -0
  160. package/Tests/Server/Services/TeamPrivilegeEscalation.test.ts +6 -0
  161. package/Tests/Server/Services/TelemetryPayAsYouGoBilling.test.ts +131 -0
  162. package/Tests/Server/Services/UserNotificationRuleAdminGuards.test.ts +13 -2
  163. package/Tests/Server/Types/Database/Permissions/ModelPermissionAnonymousRefusal.test.ts +518 -0
  164. package/Tests/Server/Types/Database/Permissions/MultiTenantPermissions.test.ts +350 -0
  165. package/Tests/Server/Types/Database/Permissions/OnCallCalendarFeedPermissions.test.ts +282 -25
  166. package/Tests/Server/Types/Database/Permissions/TableLevelBlockPermission.test.ts +459 -0
  167. package/Tests/Server/Utils/AI/AIRunPrivacyFilter.test.ts +101 -9
  168. package/Tests/Server/Utils/AI/ChatAgentHelpers.test.ts +88 -4
  169. package/Tests/Server/Utils/AI/Toolbox/ExceptionTools.test.ts +459 -0
  170. package/Tests/Server/Utils/AI/Toolbox/LogTools.test.ts +794 -0
  171. package/Tests/Server/Utils/AI/Toolbox/RecentChangesTools.test.ts +574 -0
  172. package/Tests/Server/Utils/AI/Toolbox/SecurityEventTools.test.ts +596 -0
  173. package/Tests/Server/Utils/CaptchaRequestAndLogging.test.ts +395 -0
  174. package/Tests/Server/Utils/MasterAdminPageAccess.test.ts +251 -0
  175. package/Tests/Server/Utils/Monitor/MonitorActionTimestamps.test.ts +616 -0
  176. package/Tests/Server/Utils/Realtime.test.ts +502 -0
  177. package/Tests/Server/Utils/SecurityEvent/Connectors/GoogleSecOps/GoogleSecOpsConnectorSeverity.test.ts +216 -0
  178. package/Tests/Server/Utils/SecurityEvent/DetectionRuleEvaluator.test.ts +142 -0
  179. package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsSeverityRepair.test.ts +140 -0
  180. package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsSeverityRepairClickhouseIntegration.test.ts +542 -0
  181. package/Tests/Server/Utils/Telemetry/ChangeEventRow.test.ts +743 -0
  182. package/Tests/Server/Utils/Telemetry/RuntimeMetrics.test.ts +465 -0
  183. package/Tests/Server/Utils/Workspace/MicrosoftTeams/Messages/Alert.test.ts +202 -0
  184. package/Tests/Server/Utils/Workspace/MicrosoftTeams/Messages/Incident.test.ts +194 -0
  185. package/Tests/Server/Utils/Workspace/MicrosoftTeams/Messages/ScheduledMaintenance.test.ts +231 -0
  186. package/Tests/Server/Utils/Workspace/Slack/Messages/Alert.test.ts +194 -0
  187. package/Tests/Server/Utils/Workspace/Slack/Messages/AlertEpisode.test.ts +194 -0
  188. package/Tests/Server/Utils/Workspace/Slack/Messages/Incident.test.ts +194 -0
  189. package/Tests/Server/Utils/Workspace/Slack/Messages/IncidentEpisode.test.ts +194 -0
  190. package/Tests/Server/Utils/Workspace/Slack/Messages/ScheduledMaintenance.test.ts +247 -0
  191. package/Tests/Types/AI/AIInsightEvidence.test.ts +206 -0
  192. package/Tests/Types/BaseDatabase/DatabaseCommonInteractionPropsUtilAnonymous.test.ts +144 -0
  193. package/Tests/Types/Call/CallProvider.test.ts +528 -0
  194. package/Tests/Types/Kubernetes/KubernetesCostIngest.test.ts +236 -0
  195. package/Tests/Types/OnCallDutyPolicy/ScheduleTimeline.test.ts +736 -0
  196. package/Tests/Types/OnCallDutyPolicy/ScheduleTimelineLayout.test.ts +996 -0
  197. package/Tests/Types/SecurityEvent/SigmaRule.test.ts +142 -0
  198. package/Tests/Types/Workflow/Components/JSON.test.ts +182 -0
  199. package/Tests/UI/Components/BasicFormDropdownNormalization.test.tsx +116 -1
  200. package/Tests/UI/Components/Dropdown/DropdownAsyncOptions.test.tsx +81 -0
  201. package/Tests/UI/Components/EditionLabelLicenseRefresh.test.tsx +89 -1
  202. package/Tests/UI/Components/EventAttachmentList.test.tsx +174 -0
  203. package/Tests/UI/Components/Forms/BasicFormBurnRateTemplateDefaults.test.tsx +395 -0
  204. package/Tests/UI/Components/Forms/BasicFormCollapsibleSections.test.tsx +286 -0
  205. package/Tests/UI/Components/Forms/FormSummary.test.tsx +128 -0
  206. package/Tests/UI/Components/ModelTable/BaseModelTableQueryChange.test.tsx +365 -0
  207. package/Tests/UI/Components/OpenAuthenticatedUrl.test.ts +358 -0
  208. package/Tests/UI/Components/SessionAwareImage.test.tsx +496 -0
  209. package/Tests/UI/Components/TelemetryHistogramZeroBuckets.test.tsx +190 -0
  210. package/Tests/UI/Components/TooltipInteractive.test.tsx +97 -0
  211. package/Tests/UI/MicrosoftTeams/MicrosoftTeamsChatsCardInstallGuidance.test.tsx +1 -1
  212. package/Tests/UI/Monitor/EvaluationLogListTimestamps.test.tsx +367 -0
  213. package/Tests/UI/Utils/API/BaseAPIRefreshSession.test.ts +1087 -0
  214. package/Tests/UI/Utils/API/DashboardHost.ts +12 -0
  215. package/Tests/UI/Utils/API/FakeAxiosServer.ts +183 -0
  216. package/Tests/UI/Utils/Breadcrumb/fixtures/RealBreadcrumbTrails.ts +10 -0
  217. package/Tests/UI/Utils/Breadcrumb/fixtures/RealRoutePatterns.ts +2 -0
  218. package/Tests/UI/Utils/Cookie.test.ts +440 -0
  219. package/Tests/UI/Utils/ModelAPIRequestClient.test.ts +278 -0
  220. package/Tests/UI/Utils/Navigation.test.ts +33 -0
  221. package/Tests/UI/Utils/PricingPlan.test.ts +295 -0
  222. package/Tests/UI/Utils/Realtime.test.ts +759 -0
  223. package/Tests/UI/Utils/Telemetry/Telemetry.test.ts +500 -0
  224. package/Tests/Utils/APIInstanceDispatch.test.ts +311 -0
  225. package/Tests/Utils/SecurityEvent/GoogleSecOpsAlertNormalizerSeverity.test.ts +565 -0
  226. package/Types/BaseDatabase/DatabaseCommonInteractionPropsUtil.ts +40 -0
  227. package/Types/Monitor/MonitorEvaluationSummary.ts +3 -0
  228. package/Types/OnCallDutyPolicy/ScheduleTimeline.ts +507 -0
  229. package/Types/OnCallDutyPolicy/ScheduleTimelineLayout.ts +589 -0
  230. package/Types/Realtime/EventName.ts +11 -0
  231. package/Types/SecurityEvent/DetectionFindingConstants.ts +14 -0
  232. package/Types/SecurityEvent/OcsfSeverity.ts +31 -26
  233. package/Types/SecurityEvent/SigmaRule.ts +51 -0
  234. package/Types/SecurityEvent/ThreatIntelConstants.ts +18 -0
  235. package/UI/Components/AttachmentList/EventAttachmentList.tsx +30 -2
  236. package/UI/Components/Dashboard/DashboardVariableControl.tsx +12 -2
  237. package/UI/Components/Dropdown/Dropdown.tsx +6 -1
  238. package/UI/Components/EditionLabel/EditionLabel.tsx +12 -0
  239. package/UI/Components/EventItem/EventItem.tsx +12 -1
  240. package/UI/Components/Forms/BasicForm.tsx +151 -126
  241. package/UI/Components/Forms/CollapsibleFormSection.tsx +63 -0
  242. package/UI/Components/Forms/Fields/FormField.tsx +10 -4
  243. package/UI/Components/Forms/FormSummary.tsx +7 -0
  244. package/UI/Components/Forms/Types/Field.ts +10 -0
  245. package/UI/Components/Markdown.tsx/MarkdownViewer.tsx +2 -1
  246. package/UI/Components/Markdown.tsx/SessionAwareImage.tsx +122 -0
  247. package/UI/Components/ModelTable/BaseModelTable.tsx +34 -5
  248. package/UI/Components/ModelTable/TableView.tsx +1 -1
  249. package/UI/Components/TelemetryViewer/components/TelemetryHistogram.tsx +8 -1
  250. package/UI/Components/Tooltip/Tooltip.tsx +8 -1
  251. package/UI/Utils/API/API.ts +173 -12
  252. package/UI/Utils/API/RequestOptions.ts +11 -0
  253. package/UI/Utils/AnalyticsModelAPI/AnalyticsModelAPI.ts +31 -7
  254. package/UI/Utils/ModelAPI/ModelAPI.ts +30 -9
  255. package/UI/Utils/Navigation.ts +9 -0
  256. package/UI/Utils/OpenAuthenticatedUrl.ts +154 -0
  257. package/UI/Utils/Realtime.ts +176 -30
  258. package/Utils/API.ts +14 -5
  259. package/Utils/SecurityEvent/GoogleSecOpsAlertNormalizer.ts +157 -7
  260. package/Utils/SecurityEvent/Sigma/SigmaRuleParser.ts +9 -17
  261. package/Utils/Slo/SloBurnRateTemplate.ts +2 -2
  262. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyScheduleCalendarFeed.js +1 -1
  263. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyScheduleCalendarFeed.js.map +1 -1
  264. package/build/dist/Models/DatabaseModels/ProjectOnCallCalendarFeed.js +1 -1
  265. package/build/dist/Models/DatabaseModels/ProjectOnCallCalendarFeed.js.map +1 -1
  266. package/build/dist/Models/DatabaseModels/UserOnCallCalendarFeed.js +1 -1
  267. package/build/dist/Models/DatabaseModels/UserOnCallCalendarFeed.js.map +1 -1
  268. package/build/dist/Server/API/AIBillingAPI.js +1 -1
  269. package/build/dist/Server/API/AIBillingAPI.js.map +1 -1
  270. package/build/dist/Server/API/AIInsightAPI.js +1 -4
  271. package/build/dist/Server/API/AIInsightAPI.js.map +1 -1
  272. package/build/dist/Server/API/AIInvestigationAPI.js +1 -4
  273. package/build/dist/Server/API/AIInvestigationAPI.js.map +1 -1
  274. package/build/dist/Server/API/AIReadinessAPI.js +1 -3
  275. package/build/dist/Server/API/AIReadinessAPI.js.map +1 -1
  276. package/build/dist/Server/API/AlertAPI.js +1 -1
  277. package/build/dist/Server/API/AlertAPI.js.map +1 -1
  278. package/build/dist/Server/API/AutoRemediationAPI.js +1 -4
  279. package/build/dist/Server/API/AutoRemediationAPI.js.map +1 -1
  280. package/build/dist/Server/API/BaseAPI.js +12 -0
  281. package/build/dist/Server/API/BaseAPI.js.map +1 -1
  282. package/build/dist/Server/API/BaseAnalyticsAPI.js +55 -10
  283. package/build/dist/Server/API/BaseAnalyticsAPI.js.map +1 -1
  284. package/build/dist/Server/API/BillingAPI.js +2 -2
  285. package/build/dist/Server/API/BillingAPI.js.map +1 -1
  286. package/build/dist/Server/API/BillingInvoiceAPI.js +1 -1
  287. package/build/dist/Server/API/BillingInvoiceAPI.js.map +1 -1
  288. package/build/dist/Server/API/BillingPaymentMethodAPI.js +2 -2
  289. package/build/dist/Server/API/BillingPaymentMethodAPI.js.map +1 -1
  290. package/build/dist/Server/API/CodeFixRunAPI.js +1 -3
  291. package/build/dist/Server/API/CodeFixRunAPI.js.map +1 -1
  292. package/build/dist/Server/API/CommonAPI.js +50 -5
  293. package/build/dist/Server/API/CommonAPI.js.map +1 -1
  294. package/build/dist/Server/API/DashboardAPI.js +12 -12
  295. package/build/dist/Server/API/DashboardAPI.js.map +1 -1
  296. package/build/dist/Server/API/GlobalConfigAPI.js +12 -0
  297. package/build/dist/Server/API/GlobalConfigAPI.js.map +1 -1
  298. package/build/dist/Server/API/IncidentAPI.js +2 -2
  299. package/build/dist/Server/API/IncidentAPI.js.map +1 -1
  300. package/build/dist/Server/API/IncidentEpisodeAPI.js +1 -1
  301. package/build/dist/Server/API/IncidentEpisodeAPI.js.map +1 -1
  302. package/build/dist/Server/API/NotificationAPI.js +1 -1
  303. package/build/dist/Server/API/NotificationAPI.js.map +1 -1
  304. package/build/dist/Server/API/OnCallCalendarAPI.js +1 -4
  305. package/build/dist/Server/API/OnCallCalendarAPI.js.map +1 -1
  306. package/build/dist/Server/API/OnCallDutyPolicyAPI.js +6 -0
  307. package/build/dist/Server/API/OnCallDutyPolicyAPI.js.map +1 -1
  308. package/build/dist/Server/API/OnCallReadinessAPI.js +4 -1
  309. package/build/dist/Server/API/OnCallReadinessAPI.js.map +1 -1
  310. package/build/dist/Server/API/OnCallScheduleTimelineAPI.js +494 -0
  311. package/build/dist/Server/API/OnCallScheduleTimelineAPI.js.map +1 -0
  312. package/build/dist/Server/API/ProjectAPI.js +1 -1
  313. package/build/dist/Server/API/ProjectAPI.js.map +1 -1
  314. package/build/dist/Server/API/ScheduledMaintenanceAPI.js +1 -1
  315. package/build/dist/Server/API/ScheduledMaintenanceAPI.js.map +1 -1
  316. package/build/dist/Server/API/StatusPageAPI.js +125 -33
  317. package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
  318. package/build/dist/Server/API/TeamMemberAPI.js +3 -3
  319. package/build/dist/Server/API/TeamMemberAPI.js.map +1 -1
  320. package/build/dist/Server/API/UserCallAPI.js +2 -2
  321. package/build/dist/Server/API/UserCallAPI.js.map +1 -1
  322. package/build/dist/Server/API/UserEmailAPI.js +2 -2
  323. package/build/dist/Server/API/UserEmailAPI.js.map +1 -1
  324. package/build/dist/Server/API/UserIncomingCallNumberAPI.js +2 -2
  325. package/build/dist/Server/API/UserIncomingCallNumberAPI.js.map +1 -1
  326. package/build/dist/Server/API/UserMicrosoftTeamsAPI.js +1 -1
  327. package/build/dist/Server/API/UserMicrosoftTeamsAPI.js.map +1 -1
  328. package/build/dist/Server/API/UserSlackAPI.js +1 -1
  329. package/build/dist/Server/API/UserSlackAPI.js.map +1 -1
  330. package/build/dist/Server/API/UserSmsAPI.js +2 -2
  331. package/build/dist/Server/API/UserSmsAPI.js.map +1 -1
  332. package/build/dist/Server/API/UserTotpAuthAPI.js +1 -1
  333. package/build/dist/Server/API/UserTotpAuthAPI.js.map +1 -1
  334. package/build/dist/Server/API/UserWebAuthnAPI.js +2 -2
  335. package/build/dist/Server/API/UserWebAuthnAPI.js.map +1 -1
  336. package/build/dist/Server/API/UserWebhookAPI.js +1 -1
  337. package/build/dist/Server/API/UserWebhookAPI.js.map +1 -1
  338. package/build/dist/Server/API/UserWhatsAppAPI.js +2 -2
  339. package/build/dist/Server/API/UserWhatsAppAPI.js.map +1 -1
  340. package/build/dist/Server/Middleware/MasterAdminAuthorization.js +11 -2
  341. package/build/dist/Server/Middleware/MasterAdminAuthorization.js.map +1 -1
  342. package/build/dist/Server/Middleware/UserAuthorization.js +64 -4
  343. package/build/dist/Server/Middleware/UserAuthorization.js.map +1 -1
  344. package/build/dist/Server/Services/ApiKeyPermissionService.js +80 -4
  345. package/build/dist/Server/Services/ApiKeyPermissionService.js.map +1 -1
  346. package/build/dist/Server/Services/DatabaseService.js +171 -0
  347. package/build/dist/Server/Services/DatabaseService.js.map +1 -1
  348. package/build/dist/Server/Services/DetectionRuleService.js +4 -4
  349. package/build/dist/Server/Services/DetectionRuleService.js.map +1 -1
  350. package/build/dist/Server/Services/OnCallDutyPolicyChildService.js +170 -0
  351. package/build/dist/Server/Services/OnCallDutyPolicyChildService.js.map +1 -0
  352. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js +2 -2
  353. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js.map +1 -1
  354. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleService.js +2 -2
  355. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleService.js.map +1 -1
  356. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleTeamService.js +2 -2
  357. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleTeamService.js.map +1 -1
  358. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleUserService.js +2 -2
  359. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleUserService.js.map +1 -1
  360. package/build/dist/Server/Services/PayAsYouGoBillingService.js +20 -27
  361. package/build/dist/Server/Services/PayAsYouGoBillingService.js.map +1 -1
  362. package/build/dist/Server/Services/ProjectService.js +17 -0
  363. package/build/dist/Server/Services/ProjectService.js.map +1 -1
  364. package/build/dist/Server/Services/RumSessionPinService.js +180 -16
  365. package/build/dist/Server/Services/RumSessionPinService.js.map +1 -1
  366. package/build/dist/Server/Services/TeamPermissionService.js +89 -27
  367. package/build/dist/Server/Services/TeamPermissionService.js.map +1 -1
  368. package/build/dist/Server/Services/ThreatIntelFeedService.js +5 -4
  369. package/build/dist/Server/Services/ThreatIntelFeedService.js.map +1 -1
  370. package/build/dist/Server/Types/Database/Permissions/BasePermission.js +9 -6
  371. package/build/dist/Server/Types/Database/Permissions/BasePermission.js.map +1 -1
  372. package/build/dist/Server/Types/Database/Permissions/Index.js +60 -6
  373. package/build/dist/Server/Types/Database/Permissions/Index.js.map +1 -1
  374. package/build/dist/Server/Types/Database/Permissions/TablePermission.js +14 -13
  375. package/build/dist/Server/Types/Database/Permissions/TablePermission.js.map +1 -1
  376. package/build/dist/Server/Utils/AI/AIChatPrivacyFilter.js +7 -0
  377. package/build/dist/Server/Utils/AI/AIChatPrivacyFilter.js.map +1 -1
  378. package/build/dist/Server/Utils/AI/AIRunPrivacyFilter.js +7 -0
  379. package/build/dist/Server/Utils/AI/AIRunPrivacyFilter.js.map +1 -1
  380. package/build/dist/Server/Utils/MasterAdminPageAccess.js +39 -0
  381. package/build/dist/Server/Utils/MasterAdminPageAccess.js.map +1 -0
  382. package/build/dist/Server/Utils/Monitor/MonitorAlert.js +3 -1
  383. package/build/dist/Server/Utils/Monitor/MonitorAlert.js.map +1 -1
  384. package/build/dist/Server/Utils/Monitor/MonitorIncident.js +3 -1
  385. package/build/dist/Server/Utils/Monitor/MonitorIncident.js.map +1 -1
  386. package/build/dist/Server/Utils/Realtime.js +126 -37
  387. package/build/dist/Server/Utils/Realtime.js.map +1 -1
  388. package/build/dist/Server/Utils/SecurityEvent/DetectionRuleEvaluator.js +7 -25
  389. package/build/dist/Server/Utils/SecurityEvent/DetectionRuleEvaluator.js.map +1 -1
  390. package/build/dist/Server/Utils/SecurityEvent/GoogleSecOpsSeverityRepair.js +127 -0
  391. package/build/dist/Server/Utils/SecurityEvent/GoogleSecOpsSeverityRepair.js.map +1 -0
  392. package/build/dist/Server/Utils/SecurityEvent/Sigma/SigmaClickhouseCompiler.js +1 -1
  393. package/build/dist/Server/Utils/SecurityEvent/Sigma/SigmaClickhouseCompiler.js.map +1 -1
  394. package/build/dist/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelFeedPoller.js +3 -2
  395. package/build/dist/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelFeedPoller.js.map +1 -1
  396. package/build/dist/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelMatcher.js +4 -8
  397. package/build/dist/Server/Utils/SecurityEvent/ThreatIntel/ThreatIntelMatcher.js.map +1 -1
  398. package/build/dist/Types/BaseDatabase/DatabaseCommonInteractionPropsUtil.js +31 -1
  399. package/build/dist/Types/BaseDatabase/DatabaseCommonInteractionPropsUtil.js.map +1 -1
  400. package/build/dist/Types/OnCallDutyPolicy/ScheduleTimeline.js +321 -0
  401. package/build/dist/Types/OnCallDutyPolicy/ScheduleTimeline.js.map +1 -0
  402. package/build/dist/Types/OnCallDutyPolicy/ScheduleTimelineLayout.js +372 -0
  403. package/build/dist/Types/OnCallDutyPolicy/ScheduleTimelineLayout.js.map +1 -0
  404. package/build/dist/Types/Realtime/EventName.js +10 -0
  405. package/build/dist/Types/Realtime/EventName.js.map +1 -1
  406. package/build/dist/Types/SecurityEvent/DetectionFindingConstants.js +11 -0
  407. package/build/dist/Types/SecurityEvent/DetectionFindingConstants.js.map +1 -1
  408. package/build/dist/Types/SecurityEvent/OcsfSeverity.js +30 -25
  409. package/build/dist/Types/SecurityEvent/OcsfSeverity.js.map +1 -1
  410. package/build/dist/Types/SecurityEvent/SigmaRule.js +47 -0
  411. package/build/dist/Types/SecurityEvent/SigmaRule.js.map +1 -1
  412. package/build/dist/Types/SecurityEvent/ThreatIntelConstants.js +14 -0
  413. package/build/dist/Types/SecurityEvent/ThreatIntelConstants.js.map +1 -1
  414. package/build/dist/UI/Components/AttachmentList/EventAttachmentList.js +9 -4
  415. package/build/dist/UI/Components/AttachmentList/EventAttachmentList.js.map +1 -1
  416. package/build/dist/UI/Components/Dashboard/DashboardVariableControl.js +10 -2
  417. package/build/dist/UI/Components/Dashboard/DashboardVariableControl.js.map +1 -1
  418. package/build/dist/UI/Components/Dropdown/Dropdown.js +5 -1
  419. package/build/dist/UI/Components/Dropdown/Dropdown.js.map +1 -1
  420. package/build/dist/UI/Components/EditionLabel/EditionLabel.js +11 -0
  421. package/build/dist/UI/Components/EditionLabel/EditionLabel.js.map +1 -1
  422. package/build/dist/UI/Components/EventItem/EventItem.js +2 -2
  423. package/build/dist/UI/Components/EventItem/EventItem.js.map +1 -1
  424. package/build/dist/UI/Components/Forms/BasicForm.js +70 -64
  425. package/build/dist/UI/Components/Forms/BasicForm.js.map +1 -1
  426. package/build/dist/UI/Components/Forms/CollapsibleFormSection.js +27 -0
  427. package/build/dist/UI/Components/Forms/CollapsibleFormSection.js.map +1 -0
  428. package/build/dist/UI/Components/Forms/Fields/FormField.js +10 -7
  429. package/build/dist/UI/Components/Forms/Fields/FormField.js.map +1 -1
  430. package/build/dist/UI/Components/Forms/FormSummary.js +7 -0
  431. package/build/dist/UI/Components/Forms/FormSummary.js.map +1 -1
  432. package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js +2 -1
  433. package/build/dist/UI/Components/Markdown.tsx/MarkdownViewer.js.map +1 -1
  434. package/build/dist/UI/Components/Markdown.tsx/SessionAwareImage.js +84 -0
  435. package/build/dist/UI/Components/Markdown.tsx/SessionAwareImage.js.map +1 -0
  436. package/build/dist/UI/Components/ModelTable/BaseModelTable.js +14 -1
  437. package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
  438. package/build/dist/UI/Components/ModelTable/TableView.js +1 -1
  439. package/build/dist/UI/Components/ModelTable/TableView.js.map +1 -1
  440. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryHistogram.js +8 -1
  441. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryHistogram.js.map +1 -1
  442. package/build/dist/UI/Components/Tooltip/Tooltip.js +2 -1
  443. package/build/dist/UI/Components/Tooltip/Tooltip.js.map +1 -1
  444. package/build/dist/UI/Utils/API/API.js +143 -19
  445. package/build/dist/UI/Utils/API/API.js.map +1 -1
  446. package/build/dist/UI/Utils/AnalyticsModelAPI/AnalyticsModelAPI.js +21 -7
  447. package/build/dist/UI/Utils/AnalyticsModelAPI/AnalyticsModelAPI.js.map +1 -1
  448. package/build/dist/UI/Utils/ModelAPI/ModelAPI.js +26 -9
  449. package/build/dist/UI/Utils/ModelAPI/ModelAPI.js.map +1 -1
  450. package/build/dist/UI/Utils/Navigation.js +8 -0
  451. package/build/dist/UI/Utils/Navigation.js.map +1 -1
  452. package/build/dist/UI/Utils/OpenAuthenticatedUrl.js +92 -0
  453. package/build/dist/UI/Utils/OpenAuthenticatedUrl.js.map +1 -0
  454. package/build/dist/UI/Utils/Realtime.js +120 -15
  455. package/build/dist/UI/Utils/Realtime.js.map +1 -1
  456. package/build/dist/Utils/API.js +13 -5
  457. package/build/dist/Utils/API.js.map +1 -1
  458. package/build/dist/Utils/SecurityEvent/GoogleSecOpsAlertNormalizer.js +123 -6
  459. package/build/dist/Utils/SecurityEvent/GoogleSecOpsAlertNormalizer.js.map +1 -1
  460. package/build/dist/Utils/SecurityEvent/Sigma/SigmaRuleParser.js +4 -18
  461. package/build/dist/Utils/SecurityEvent/Sigma/SigmaRuleParser.js.map +1 -1
  462. package/build/dist/Utils/Slo/SloBurnRateTemplate.js +2 -2
  463. package/package.json +1 -1
@@ -0,0 +1,563 @@
1
+ import CommonAPI from "../../../Server/API/CommonAPI";
2
+ import UserMiddleware from "../../../Server/Middleware/UserAuthorization";
3
+ import {
4
+ ExpressResponse,
5
+ NextFunction,
6
+ OneUptimeRequest,
7
+ } from "../../../Server/Utils/Express";
8
+ import Response from "../../../Server/Utils/Response";
9
+ import Dictionary from "../../../Types/Dictionary";
10
+ import Exception from "../../../Types/Exception/Exception";
11
+ import ExceptionCode from "../../../Types/Exception/ExceptionCode";
12
+ import NotAuthenticatedException from "../../../Types/Exception/NotAuthenticatedException";
13
+ import NotAuthorizedException from "../../../Types/Exception/NotAuthorizedException";
14
+ import JSONWebTokenData from "../../../Types/JsonWebTokenData";
15
+ import ObjectID from "../../../Types/ObjectID";
16
+ import Permission, {
17
+ UserPermission,
18
+ UserTenantAccessPermission,
19
+ } from "../../../Types/Permission";
20
+ import UserType from "../../../Types/UserType";
21
+ import { getJestSpyOn } from "../../Spy";
22
+ import { afterEach, beforeEach, describe, expect, test } from "@jest/globals";
23
+
24
+ /*
25
+ * The request-level half of the expired-session fix.
26
+ *
27
+ * THE BUG
28
+ *
29
+ * The access-token cookie's maxAge is the JWT's own 15 minute lifetime, so a
30
+ * Dashboard tab left open longer than that sends its next request with no
31
+ * token at all. getUserMiddleware does not refuse such a request: it marks it
32
+ * UserType.Public and lets it through, because plenty of routes (status pages,
33
+ * public dashboards, CRUD reads of Public-permission models) are meant to be
34
+ * reachable anonymously. Whatever runs next decides.
35
+ *
36
+ * The browser client (Common/UI/Utils/API/API.ts) refreshes the session and
37
+ * replays the request ONLY on a 401. Everything that refused the anonymous
38
+ * request with anything else - a 422 NotAuthorizedException ("You are not
39
+ * authorized to access this project's data", "Project ID is required to
40
+ * access this resource") or a 400 - surfaced as a hard error to a user whose
41
+ * only problem was an idle tab.
42
+ *
43
+ * WHAT THIS FILE PINS
44
+ *
45
+ * 1. isAnonymousRequest is exactly "getUserMiddleware found neither a token
46
+ * nor an API key": userType unset or Public. API keys and master admins
47
+ * are credentials, not anonymity.
48
+ * 2. requireUserAuthentication answers an anonymous request with a 401 and
49
+ * admits every credentialed one - including API keys, so automation on
50
+ * the routes that gained this guard keeps working.
51
+ * 3. requirePermission asks "who are you?" BEFORE "which project?" and
52
+ * "what may you do?". An anonymous request with no tenant used to get
53
+ * the 422 "Project ID is required"; it now gets the 401, because no
54
+ * answer about tenants or permissions means anything until the caller
55
+ * has credentials. Every refusal of a credentialed caller is unchanged.
56
+ *
57
+ * Response.sendErrorResponse is spied on and silenced, so the assertion is on
58
+ * the exception the middleware chose - its class and its code - rather than
59
+ * on how Express would serialize it.
60
+ */
61
+
62
+ const AUTHENTICATION_REQUIRED_MESSAGE: string =
63
+ "Authentication required. Please log in to access this resource.";
64
+
65
+ const PROJECT_ID: ObjectID = new ObjectID(
66
+ "11111111-1111-4111-8111-111111111111",
67
+ );
68
+ const OTHER_PROJECT_ID: ObjectID = new ObjectID(
69
+ "22222222-2222-4222-8222-222222222222",
70
+ );
71
+ const USER_ID: ObjectID = new ObjectID("33333333-3333-4333-8333-333333333333");
72
+
73
+ type RequestFixture = {
74
+ userType?: UserType | undefined;
75
+ tenantId?: ObjectID | undefined;
76
+ userAuthorization?: Partial<JSONWebTokenData> | undefined;
77
+ userTenantAccessPermission?:
78
+ | Dictionary<UserTenantAccessPermission>
79
+ | undefined;
80
+ };
81
+
82
+ type BuildRequestFunction = (fixture: RequestFixture) => OneUptimeRequest;
83
+
84
+ const buildRequest: BuildRequestFunction = (
85
+ fixture: RequestFixture,
86
+ ): OneUptimeRequest => {
87
+ return {
88
+ headers: {},
89
+ params: {},
90
+ query: {},
91
+ body: {},
92
+ ...fixture,
93
+ } as unknown as OneUptimeRequest;
94
+ };
95
+
96
+ type TenantPermissionFunction = (data: {
97
+ projectId: ObjectID;
98
+ permissions: Array<Permission>;
99
+ }) => Dictionary<UserTenantAccessPermission>;
100
+
101
+ const tenantPermission: TenantPermissionFunction = (data: {
102
+ projectId: ObjectID;
103
+ permissions: Array<Permission>;
104
+ }): Dictionary<UserTenantAccessPermission> => {
105
+ return {
106
+ [data.projectId.toString()]: {
107
+ _type: "UserTenantAccessPermission",
108
+ projectId: data.projectId,
109
+ permissions: data.permissions.map(
110
+ (permission: Permission): UserPermission => {
111
+ return {
112
+ _type: "UserPermission",
113
+ permission: permission,
114
+ labelIds: [],
115
+ };
116
+ },
117
+ ),
118
+ },
119
+ };
120
+ };
121
+
122
+ type MiddlewareCallResult = {
123
+ nextCalls: Array<Array<unknown>>;
124
+ sentError: Exception | undefined;
125
+ sendErrorCallCount: number;
126
+ };
127
+
128
+ type MiddlewareFunction = (
129
+ req: OneUptimeRequest,
130
+ res: ExpressResponse,
131
+ next: NextFunction,
132
+ ) => Promise<void>;
133
+
134
+ type CallMiddlewareFunction = (
135
+ middleware: MiddlewareFunction,
136
+ req: OneUptimeRequest,
137
+ ) => Promise<MiddlewareCallResult>;
138
+
139
+ const callMiddleware: CallMiddlewareFunction = async (
140
+ middleware: MiddlewareFunction,
141
+ req: OneUptimeRequest,
142
+ ): Promise<MiddlewareCallResult> => {
143
+ const res: ExpressResponse = {
144
+ status: jest.fn().mockReturnThis(),
145
+ json: jest.fn().mockReturnThis(),
146
+ send: jest.fn().mockReturnThis(),
147
+ } as unknown as ExpressResponse;
148
+
149
+ const next: jest.Mock = jest.fn();
150
+
151
+ await middleware(req, res, next as unknown as NextFunction);
152
+
153
+ const errorCalls: Array<Array<unknown>> = (
154
+ Response.sendErrorResponse as unknown as jest.Mock
155
+ ).mock.calls as Array<Array<unknown>>;
156
+
157
+ return {
158
+ nextCalls: next.mock.calls as Array<Array<unknown>>,
159
+ sentError: errorCalls[0]?.[2] as Exception | undefined,
160
+ sendErrorCallCount: errorCalls.length,
161
+ };
162
+ };
163
+
164
+ type ExpectRefusedFunction = (result: MiddlewareCallResult) => void;
165
+
166
+ const expectUnauthenticated: ExpectRefusedFunction = (
167
+ result: MiddlewareCallResult,
168
+ ): void => {
169
+ expect(result.nextCalls).toHaveLength(0);
170
+ expect(result.sendErrorCallCount).toBe(1);
171
+ expect(result.sentError).toBeInstanceOf(NotAuthenticatedException);
172
+ expect(result.sentError?.code).toBe(ExceptionCode.NotAuthenticatedException);
173
+ expect(result.sentError?.code).toBe(401);
174
+ expect(result.sentError?.message).toBe(AUTHENTICATION_REQUIRED_MESSAGE);
175
+ };
176
+
177
+ type ExpectForbiddenFunction = (
178
+ result: MiddlewareCallResult,
179
+ message: string,
180
+ ) => void;
181
+
182
+ const expectNotAuthorized: ExpectForbiddenFunction = (
183
+ result: MiddlewareCallResult,
184
+ message: string,
185
+ ): void => {
186
+ expect(result.nextCalls).toHaveLength(0);
187
+ expect(result.sendErrorCallCount).toBe(1);
188
+ expect(result.sentError).toBeInstanceOf(NotAuthorizedException);
189
+ expect(result.sentError?.code).toBe(ExceptionCode.NotAuthorizedException);
190
+ expect(result.sentError?.code).toBe(422);
191
+ expect(result.sentError?.message).toBe(message);
192
+ };
193
+
194
+ type ExpectPassedFunction = (result: MiddlewareCallResult) => void;
195
+
196
+ const expectPassed: ExpectPassedFunction = (
197
+ result: MiddlewareCallResult,
198
+ ): void => {
199
+ expect(result.sendErrorCallCount).toBe(0);
200
+ expect(result.nextCalls).toHaveLength(1);
201
+ // next() with an argument is Express's error path, not a pass.
202
+ expect(result.nextCalls[0]).toEqual([]);
203
+ };
204
+
205
+ beforeEach(() => {
206
+ jest.clearAllMocks();
207
+
208
+ getJestSpyOn(Response, "sendErrorResponse").mockImplementation(() => {
209
+ return undefined as never;
210
+ });
211
+ });
212
+
213
+ afterEach(() => {
214
+ jest.restoreAllMocks();
215
+ });
216
+
217
+ describe("UserMiddleware.AUTHENTICATION_REQUIRED_MESSAGE", () => {
218
+ /*
219
+ * The request-level and the props-level refusal are two halves of one
220
+ * contract with the client, and a user who hits one route and then another
221
+ * should not see two different sentences for the same expired session.
222
+ */
223
+ test("is the same sentence CommonAPI uses", () => {
224
+ expect(UserMiddleware.AUTHENTICATION_REQUIRED_MESSAGE).toBe(
225
+ AUTHENTICATION_REQUIRED_MESSAGE,
226
+ );
227
+ expect(UserMiddleware.AUTHENTICATION_REQUIRED_MESSAGE).toBe(
228
+ CommonAPI.AUTHENTICATION_REQUIRED_MESSAGE,
229
+ );
230
+ });
231
+ });
232
+
233
+ describe("UserMiddleware.isAnonymousRequest", () => {
234
+ test.each([
235
+ ["no userType at all (getUserMiddleware never ran)", undefined, true],
236
+ ["UserType.Public (no token, no API key)", UserType.Public, true],
237
+ ["UserType.User (a decoded session)", UserType.User, false],
238
+ ["UserType.API (a project API key)", UserType.API, false],
239
+ [
240
+ "UserType.MasterAdmin (a master admin session)",
241
+ UserType.MasterAdmin,
242
+ false,
243
+ ],
244
+ ])(
245
+ "%s -> anonymous: %p",
246
+ (_label: string, userType: UserType | undefined, expected: boolean) => {
247
+ expect(
248
+ UserMiddleware.isAnonymousRequest(buildRequest({ userType: userType })),
249
+ ).toBe(expected);
250
+ },
251
+ );
252
+
253
+ /*
254
+ * The decision keys on userType alone, which is what getUserMiddleware
255
+ * sets. Stray session-shaped data on a Public request (a tenant, a
256
+ * userAuthorization object, a permission map) must not promote it.
257
+ */
258
+ test("ignores session-shaped data on a Public request", () => {
259
+ expect(
260
+ UserMiddleware.isAnonymousRequest(
261
+ buildRequest({
262
+ userType: UserType.Public,
263
+ tenantId: PROJECT_ID,
264
+ userAuthorization: { userId: USER_ID },
265
+ userTenantAccessPermission: tenantPermission({
266
+ projectId: PROJECT_ID,
267
+ permissions: [Permission.ProjectOwner],
268
+ }),
269
+ }),
270
+ ),
271
+ ).toBe(true);
272
+ });
273
+
274
+ /*
275
+ * A master admin session carries no userId requirement here, and an API
276
+ * key carries no userId at all. Neither is anonymous.
277
+ */
278
+ test("does not need a userId to call a request credentialed", () => {
279
+ expect(
280
+ UserMiddleware.isAnonymousRequest(
281
+ buildRequest({ userType: UserType.API }),
282
+ ),
283
+ ).toBe(false);
284
+ expect(
285
+ UserMiddleware.isAnonymousRequest(
286
+ buildRequest({ userType: UserType.MasterAdmin }),
287
+ ),
288
+ ).toBe(false);
289
+ });
290
+ });
291
+
292
+ describe("UserMiddleware.requireUserAuthentication", () => {
293
+ test.each([
294
+ ["no userType", undefined],
295
+ ["UserType.Public", UserType.Public],
296
+ ])(
297
+ "answers a request with %s with a 401",
298
+ async (_label: string, userType: UserType | undefined) => {
299
+ const result: MiddlewareCallResult = await callMiddleware(
300
+ UserMiddleware.requireUserAuthentication as MiddlewareFunction,
301
+ buildRequest({ userType: userType, tenantId: PROJECT_ID }),
302
+ );
303
+
304
+ expectUnauthenticated(result);
305
+ },
306
+ );
307
+
308
+ test.each([
309
+ ["a signed-in user", UserType.User, { userId: USER_ID }],
310
+ ["a project API key", UserType.API, undefined],
311
+ [
312
+ "a master admin",
313
+ UserType.MasterAdmin,
314
+ { userId: USER_ID, isMasterAdmin: true },
315
+ ],
316
+ ])(
317
+ "lets %s through",
318
+ async (
319
+ _label: string,
320
+ userType: UserType,
321
+ userAuthorization: Partial<JSONWebTokenData> | undefined,
322
+ ) => {
323
+ const result: MiddlewareCallResult = await callMiddleware(
324
+ UserMiddleware.requireUserAuthentication as MiddlewareFunction,
325
+ buildRequest({
326
+ userType: userType,
327
+ tenantId: PROJECT_ID,
328
+ userAuthorization: userAuthorization,
329
+ }),
330
+ );
331
+
332
+ expectPassed(result);
333
+ },
334
+ );
335
+
336
+ /*
337
+ * This guard is presence-only. Tenant and permission checks belong to
338
+ * whatever follows it, so a credentialed request with no tenant is still
339
+ * let through here - the refusal, if any, comes later and stays a 4xx the
340
+ * client treats as final.
341
+ */
342
+ test("does not look at the tenant", async () => {
343
+ const result: MiddlewareCallResult = await callMiddleware(
344
+ UserMiddleware.requireUserAuthentication as MiddlewareFunction,
345
+ buildRequest({ userType: UserType.User, userAuthorization: {} }),
346
+ );
347
+
348
+ expectPassed(result);
349
+ });
350
+ });
351
+
352
+ describe("UserMiddleware.requirePermission", () => {
353
+ const guard: MiddlewareFunction = UserMiddleware.requirePermission({
354
+ permissions: [Permission.ProjectOwner, Permission.ProjectAdmin],
355
+ }) as MiddlewareFunction;
356
+
357
+ describe("an anonymous request", () => {
358
+ test.each([
359
+ ["no userType", undefined],
360
+ ["UserType.Public", UserType.Public],
361
+ ])(
362
+ "with %s and a tenant gets a 401",
363
+ async (_label: string, userType: UserType | undefined) => {
364
+ const result: MiddlewareCallResult = await callMiddleware(
365
+ guard,
366
+ buildRequest({ userType: userType, tenantId: PROJECT_ID }),
367
+ );
368
+
369
+ expectUnauthenticated(result);
370
+ },
371
+ );
372
+
373
+ /*
374
+ * The ordering this change is about. This request used to get
375
+ * "Project ID is required to access this resource." (422). The tenantid
376
+ * header is the Dashboard's, not the session's, so its absence says
377
+ * nothing about why the caller is anonymous - and a 422 here would stop
378
+ * the client from refreshing a session that is merely expired.
379
+ */
380
+ test.each([
381
+ ["no userType", undefined],
382
+ ["UserType.Public", UserType.Public],
383
+ ])(
384
+ "with %s and NO tenant still gets the 401, not the tenant 422",
385
+ async (_label: string, userType: UserType | undefined) => {
386
+ const result: MiddlewareCallResult = await callMiddleware(
387
+ guard,
388
+ buildRequest({ userType: userType }),
389
+ );
390
+
391
+ expectUnauthenticated(result);
392
+ expect(result.sentError?.message).not.toBe(
393
+ "Project ID is required to access this resource.",
394
+ );
395
+ },
396
+ );
397
+
398
+ /*
399
+ * Permission data that somehow survived onto an anonymous request is not
400
+ * a credential. Only userType is.
401
+ */
402
+ test("gets a 401 even when it carries a matching permission map", async () => {
403
+ const result: MiddlewareCallResult = await callMiddleware(
404
+ guard,
405
+ buildRequest({
406
+ userType: UserType.Public,
407
+ tenantId: PROJECT_ID,
408
+ userTenantAccessPermission: tenantPermission({
409
+ projectId: PROJECT_ID,
410
+ permissions: [Permission.ProjectOwner],
411
+ }),
412
+ }),
413
+ );
414
+
415
+ expectUnauthenticated(result);
416
+ });
417
+ });
418
+
419
+ describe("a master admin", () => {
420
+ test("bypasses the tenant and permission checks", async () => {
421
+ const result: MiddlewareCallResult = await callMiddleware(
422
+ guard,
423
+ buildRequest({
424
+ userType: UserType.MasterAdmin,
425
+ userAuthorization: { userId: USER_ID, isMasterAdmin: true },
426
+ }),
427
+ );
428
+
429
+ expectPassed(result);
430
+ });
431
+ });
432
+
433
+ describe("a signed-in user (unchanged refusals)", () => {
434
+ test("without a tenant gets the 422 'Project ID is required'", async () => {
435
+ const result: MiddlewareCallResult = await callMiddleware(
436
+ guard,
437
+ buildRequest({
438
+ userType: UserType.User,
439
+ userAuthorization: { userId: USER_ID },
440
+ }),
441
+ );
442
+
443
+ expectNotAuthorized(
444
+ result,
445
+ "Project ID is required to access this resource.",
446
+ );
447
+ });
448
+
449
+ test("with no permissions in the tenant gets a 422", async () => {
450
+ const result: MiddlewareCallResult = await callMiddleware(
451
+ guard,
452
+ buildRequest({
453
+ userType: UserType.User,
454
+ tenantId: PROJECT_ID,
455
+ userAuthorization: { userId: USER_ID },
456
+ userTenantAccessPermission: tenantPermission({
457
+ projectId: OTHER_PROJECT_ID,
458
+ permissions: [Permission.ProjectOwner],
459
+ }),
460
+ }),
461
+ );
462
+
463
+ expectNotAuthorized(
464
+ result,
465
+ "You do not have permission to access this project.",
466
+ );
467
+ });
468
+
469
+ test("without the required permission gets a 422", async () => {
470
+ const result: MiddlewareCallResult = await callMiddleware(
471
+ guard,
472
+ buildRequest({
473
+ userType: UserType.User,
474
+ tenantId: PROJECT_ID,
475
+ userAuthorization: { userId: USER_ID },
476
+ userTenantAccessPermission: tenantPermission({
477
+ projectId: PROJECT_ID,
478
+ permissions: [Permission.ProjectMember],
479
+ }),
480
+ }),
481
+ );
482
+
483
+ expectNotAuthorized(
484
+ result,
485
+ "You do not have the required permission to perform this action.",
486
+ );
487
+ });
488
+
489
+ test.each([Permission.ProjectOwner, Permission.ProjectAdmin])(
490
+ "with %s is let through",
491
+ async (permission: Permission) => {
492
+ const result: MiddlewareCallResult = await callMiddleware(
493
+ guard,
494
+ buildRequest({
495
+ userType: UserType.User,
496
+ tenantId: PROJECT_ID,
497
+ userAuthorization: { userId: USER_ID },
498
+ userTenantAccessPermission: tenantPermission({
499
+ projectId: PROJECT_ID,
500
+ permissions: [Permission.ProjectMember, permission],
501
+ }),
502
+ }),
503
+ );
504
+
505
+ expectPassed(result);
506
+ },
507
+ );
508
+ });
509
+
510
+ /*
511
+ * A project API key is a credential: it is not anonymous, so it is judged
512
+ * on its tenant and permissions like a user, and keeps exactly the answers
513
+ * it had before this change.
514
+ */
515
+ describe("a project API key (unchanged)", () => {
516
+ test("without a tenant gets the 422 'Project ID is required'", async () => {
517
+ const result: MiddlewareCallResult = await callMiddleware(
518
+ guard,
519
+ buildRequest({ userType: UserType.API }),
520
+ );
521
+
522
+ expectNotAuthorized(
523
+ result,
524
+ "Project ID is required to access this resource.",
525
+ );
526
+ });
527
+
528
+ test("with the required permission is let through", async () => {
529
+ const result: MiddlewareCallResult = await callMiddleware(
530
+ guard,
531
+ buildRequest({
532
+ userType: UserType.API,
533
+ tenantId: PROJECT_ID,
534
+ userTenantAccessPermission: tenantPermission({
535
+ projectId: PROJECT_ID,
536
+ permissions: [Permission.ProjectAdmin],
537
+ }),
538
+ }),
539
+ );
540
+
541
+ expectPassed(result);
542
+ });
543
+
544
+ test("without the required permission gets a 422", async () => {
545
+ const result: MiddlewareCallResult = await callMiddleware(
546
+ guard,
547
+ buildRequest({
548
+ userType: UserType.API,
549
+ tenantId: PROJECT_ID,
550
+ userTenantAccessPermission: tenantPermission({
551
+ projectId: PROJECT_ID,
552
+ permissions: [Permission.ProjectMember],
553
+ }),
554
+ }),
555
+ );
556
+
557
+ expectNotAuthorized(
558
+ result,
559
+ "You do not have the required permission to perform this action.",
560
+ );
561
+ });
562
+ });
563
+ });