@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
@@ -495,6 +495,49 @@ export default class UserMiddleware {
495
495
  req: ExpressRequest,
496
496
  res: ExpressResponse,
497
497
  next: NextFunction,
498
+ ): Promise<void> {
499
+ return await UserMiddleware.resolveRequestUser(req, res, next, {
500
+ treatInvalidAccessTokenAsAnonymous: false,
501
+ });
502
+ }
503
+
504
+ /*
505
+ * getUserMiddleware for the anonymous surfaces: the public dashboard and
506
+ * public status page routes. Their handlers decide access themselves
507
+ * (DashboardService / StatusPageService.hasReadAccess: public flag, IP
508
+ * allowlist, master-password cookie, the page's own session cookie) and
509
+ * never read the caller's user identity.
510
+ *
511
+ * The one difference: an access token that is present but cannot be decoded
512
+ * makes the request anonymous (UserType.Public) instead of answering 401.
513
+ * The host-wide dashboard access-token cookie reaches these routes whenever
514
+ * the page is served from the dashboard's host (the preview routes), and it
515
+ * can stay in the browser after it stops decoding - an encryption-secret
516
+ * rotation, say. The public clients cannot refresh a dashboard session, so
517
+ * that 401 only ever meant "sent back to the login route": a reload loop on
518
+ * the preview route, and a password prompt for a master password the viewer
519
+ * already entered.
520
+ *
521
+ * A token that does decode is still resolved exactly as getUserMiddleware
522
+ * resolves it, and an API key is still validated. Never mount this on a
523
+ * route that needs to know who the caller is.
524
+ */
525
+ @CaptureSpan()
526
+ public static async getPublicRouteUserMiddleware(
527
+ req: ExpressRequest,
528
+ res: ExpressResponse,
529
+ next: NextFunction,
530
+ ): Promise<void> {
531
+ return await UserMiddleware.resolveRequestUser(req, res, next, {
532
+ treatInvalidAccessTokenAsAnonymous: true,
533
+ });
534
+ }
535
+
536
+ private static async resolveRequestUser(
537
+ req: ExpressRequest,
538
+ res: ExpressResponse,
539
+ next: NextFunction,
540
+ options: { treatInvalidAccessTokenAsAnonymous: boolean },
498
541
  ): Promise<void> {
499
542
  const tenantId: ObjectID | null = ProjectMiddleware.getProjectId(req);
500
543
  const oneuptimeRequest: OneUptimeRequest = req as OneUptimeRequest;
@@ -529,6 +572,12 @@ export default class UserMiddleware {
529
572
  try {
530
573
  oneuptimeRequest.userAuthorization = JSONWebToken.decode(accessToken);
531
574
  } catch (err) {
575
+ if (options.treatInvalidAccessTokenAsAnonymous) {
576
+ // decode() has already logged why the token was refused.
577
+ oneuptimeRequest.userType = UserType.Public;
578
+ return next();
579
+ }
580
+
532
581
  // if the token is invalid or expired, return 401 so clients can refresh the token.
533
582
  logger.error(err, getLogAttributesFromRequest(oneuptimeRequest));
534
583
  return Response.sendErrorResponse(
@@ -712,15 +761,12 @@ export default class UserMiddleware {
712
761
  ): Promise<void> {
713
762
  const oneuptimeRequest: OneUptimeRequest = req as OneUptimeRequest;
714
763
 
715
- if (
716
- !oneuptimeRequest.userType ||
717
- oneuptimeRequest.userType === UserType.Public
718
- ) {
764
+ if (UserMiddleware.isAnonymousRequest(oneuptimeRequest)) {
719
765
  return Response.sendErrorResponse(
720
766
  req,
721
767
  res,
722
768
  new NotAuthenticatedException(
723
- "Authentication required. Please log in to access this resource.",
769
+ UserMiddleware.AUTHENTICATION_REQUIRED_MESSAGE,
724
770
  ),
725
771
  );
726
772
  }
@@ -728,6 +774,19 @@ export default class UserMiddleware {
728
774
  return next();
729
775
  }
730
776
 
777
+ // Same wording as CommonAPI.AUTHENTICATION_REQUIRED_MESSAGE.
778
+ public static readonly AUTHENTICATION_REQUIRED_MESSAGE: string =
779
+ "Authentication required. Please log in to access this resource.";
780
+
781
+ /*
782
+ * The request-level twin of CommonAPI.isAnonymous: getUserMiddleware found
783
+ * no access token and no API key. Usually an expired session, since the
784
+ * access-token cookie expires with the JWT inside it.
785
+ */
786
+ public static isAnonymousRequest(req: OneUptimeRequest): boolean {
787
+ return !req.userType || req.userType === UserType.Public;
788
+ }
789
+
731
790
  public static requirePermission(data: {
732
791
  permissions: Array<Permission>;
733
792
  }): (
@@ -742,6 +801,21 @@ export default class UserMiddleware {
742
801
  ): Promise<void> => {
743
802
  const oneuptimeRequest: OneUptimeRequest = req as OneUptimeRequest;
744
803
 
804
+ /*
805
+ * An anonymous caller has no permissions to compare, and telling it so
806
+ * with a 422 would stop the browser client from refreshing an expired
807
+ * session. Ask who it is first.
808
+ */
809
+ if (UserMiddleware.isAnonymousRequest(oneuptimeRequest)) {
810
+ return Response.sendErrorResponse(
811
+ req,
812
+ res,
813
+ new NotAuthenticatedException(
814
+ UserMiddleware.AUTHENTICATION_REQUIRED_MESSAGE,
815
+ ),
816
+ );
817
+ }
818
+
745
819
  // Master admins bypass permission checks
746
820
  if (oneuptimeRequest.userType === UserType.MasterAdmin) {
747
821
  return next();
@@ -2,6 +2,7 @@ import CreateBy from "../Types/Database/CreateBy";
2
2
  import DeleteBy from "../Types/Database/DeleteBy";
3
3
  import { OnCreate, OnDelete, OnUpdate } from "../Types/Database/Hooks";
4
4
  import QueryHelper from "../Types/Database/QueryHelper";
5
+ import ModelPermission from "../Types/Database/Permissions/Index";
5
6
  import UpdateBy from "../Types/Database/UpdateBy";
6
7
  import ApiKeyService from "./ApiKeyService";
7
8
  import DatabaseService from "./DatabaseService";
@@ -10,7 +11,7 @@ import DatabaseCommonInteractionPropsUtil, {
10
11
  PermissionType,
11
12
  } from "../../Types/BaseDatabase/DatabaseCommonInteractionPropsUtil";
12
13
  import PermissionScope from "../../Types/Database/AccessControl/PermissionScope";
13
- import LIMIT_MAX, { LIMIT_PER_PROJECT } from "../../Types/Database/LimitMax";
14
+ import LIMIT_MAX from "../../Types/Database/LimitMax";
14
15
  import BadDataException from "../../Types/Exception/BadDataException";
15
16
  import Exception from "../../Types/Exception/Exception";
16
17
  import NotAuthorizedException from "../../Types/Exception/NotAuthorizedException";
@@ -493,8 +494,27 @@ export class Service extends DatabaseService<Model> {
493
494
  */
494
495
  this.clearCache();
495
496
 
496
- const existingPermissions: Array<Model> = await this.findBy({
497
+ updateBy.query = await ModelPermission.checkUpdateQueryPermissions(
498
+ Model,
499
+ updateBy.query,
500
+ updateBy.data,
501
+ updateBy.props,
502
+ );
503
+ const selectedPermissions: Array<Model> = await this.findAllBy({
497
504
  query: updateBy.query,
505
+ select: { _id: true },
506
+ skip: updateBy.skip,
507
+ limit: updateBy.limit,
508
+ props: { isRoot: true },
509
+ });
510
+ const selectedIds: Array<ObjectID> = selectedPermissions.map(
511
+ (row: Model) => {
512
+ return row.id!;
513
+ },
514
+ );
515
+ // Reload by ID so a label filter cannot hide part of a saved block's scope.
516
+ const existingPermissions: Array<Model> = await this.findAllBy({
517
+ query: { _id: QueryHelper.any(selectedIds) },
498
518
  select: {
499
519
  _id: true,
500
520
  labels: true,
@@ -503,8 +523,6 @@ export class Service extends DatabaseService<Model> {
503
523
  apiKeyId: true,
504
524
  permission: true,
505
525
  },
506
- limit: LIMIT_PER_PROJECT,
507
- skip: 0,
508
526
  props: {
509
527
  isRoot: true,
510
528
  },
@@ -565,6 +583,15 @@ export class Service extends DatabaseService<Model> {
565
583
  }
566
584
 
567
585
  await this.assertApiKeyBelongsToProject(apiKeyId, projectId);
586
+ // Changing a block's permission or labels can restore its old scope.
587
+ if (existingPermission.isBlockPermission) {
588
+ this.assertCallerCanGrantPermission({
589
+ permission: existingPermission.permission!,
590
+ labels: existingPermission.labels,
591
+ projectId,
592
+ props: updateBy.props,
593
+ });
594
+ }
568
595
  this.assertCallerCanGrantPermission({
569
596
  permission,
570
597
  labels: isLabelsUpdateRequested
@@ -647,6 +674,8 @@ export class Service extends DatabaseService<Model> {
647
674
  }
648
675
  }
649
676
 
677
+ updateBy.query = { ...updateBy.query, _id: QueryHelper.any(selectedIds) };
678
+ updateBy.skip = 0;
650
679
  return { updateBy, carryForward: null };
651
680
  }
652
681
 
@@ -655,6 +684,74 @@ export class Service extends DatabaseService<Model> {
655
684
  deleteBy: DeleteBy<Model>,
656
685
  ): Promise<OnDelete<Model>> {
657
686
  this.clearCache();
687
+
688
+ if (!deleteBy.props.isRoot && !deleteBy.props.isMasterAdmin) {
689
+ // Hooks run before DatabaseService applies the delete ACL and tenant.
690
+ deleteBy.query = await ModelPermission.checkDeleteQueryPermission(
691
+ Model,
692
+ deleteBy.query,
693
+ deleteBy.props,
694
+ );
695
+ const selectedPermissions: Array<Model> = await this.findAllBy({
696
+ query: deleteBy.query,
697
+ select: { _id: true },
698
+ skip: deleteBy.skip,
699
+ limit: deleteBy.limit,
700
+ props: { isRoot: true },
701
+ });
702
+ const selectedIds: Array<ObjectID> = selectedPermissions.map(
703
+ (row: Model) => {
704
+ return row.id!;
705
+ },
706
+ );
707
+ // A relation filter may select a row, but must not trim its saved labels.
708
+ const permissions: Array<Model> = await this.findAllBy({
709
+ query: { _id: QueryHelper.any(selectedIds) },
710
+ select: {
711
+ _id: true,
712
+ projectId: true,
713
+ permission: true,
714
+ labels: { _id: true },
715
+ isBlockPermission: true,
716
+ },
717
+ props: { isRoot: true },
718
+ });
719
+
720
+ for (const permission of permissions) {
721
+ /*
722
+ * Revoking an allow cannot expand access. Removing a deny can expose
723
+ * an existing allow, so it requires authority over the entire deny.
724
+ */
725
+ if (permission.isBlockPermission) {
726
+ if (!permission.projectId || !permission.permission) {
727
+ throw new BadDataException("Invalid API Key permission");
728
+ }
729
+ if (
730
+ !deleteBy.props.tenantId ||
731
+ deleteBy.props.tenantId.toString() !==
732
+ permission.projectId.toString()
733
+ ) {
734
+ throw new BadDataException("Invalid API Key ID for this project");
735
+ }
736
+ this.assertCallerCanGrantPermission({
737
+ permission: permission.permission,
738
+ labels: permission.labels,
739
+ projectId: permission.projectId,
740
+ props: deleteBy.props,
741
+ });
742
+ }
743
+ }
744
+
745
+ /*
746
+ * Delete exactly the checked page, even when the query matches more
747
+ * than one batch. The original offset has already been applied.
748
+ */
749
+ deleteBy.query = {
750
+ ...deleteBy.query,
751
+ _id: QueryHelper.any(selectedIds),
752
+ };
753
+ deleteBy.skip = 0;
754
+ }
658
755
  return { deleteBy, carryForward: null };
659
756
  }
660
757
 
@@ -22,6 +22,8 @@ import {
22
22
  OnUpdate,
23
23
  } from "../Types/Database/Hooks";
24
24
  import ModelPermission from "../Types/Database/Permissions/Index";
25
+ import PublicPermission from "../Types/Database/Permissions/PublicPermission";
26
+ import DatabaseRequestType from "../Types/BaseDatabase/DatabaseRequestType";
25
27
  import OwnerOnlyColumnPermission from "../Types/Database/Permissions/OwnerOnlyColumnPermission";
26
28
  import { CheckReadPermissionType } from "../Types/Database/Permissions/ReadPermission";
27
29
  import Query from "../Types/Database/Query";
@@ -57,6 +59,7 @@ import PartialEntity from "../../Types/Database/PartialEntity";
57
59
  import { TableColumnMetadata } from "../../Types/Database/TableColumn";
58
60
  import TableColumnType from "../../Types/Database/TableColumnType";
59
61
  import { getUniqueColumnsBy } from "../../Types/Database/UniqueColumnBy";
62
+ import QueryOperator from "../../Types/BaseDatabase/QueryOperator";
60
63
  import OneUptimeDate from "../../Types/Date";
61
64
  import Dictionary from "../../Types/Dictionary";
62
65
  import BadDataException from "../../Types/Exception/BadDataException";
@@ -96,6 +99,7 @@ import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
96
99
  import type AuditLogServiceType from "./AuditLogService";
97
100
  import EnableAuditLogOn from "../../Types/BaseDatabase/EnableAuditLogOn";
98
101
  import RelationValueUtil from "../Utils/Database/RelationValueUtil";
102
+ import RelationIdUtil from "../Utils/Database/RelationIdUtil";
99
103
 
100
104
  const RULE_CRITERIA_RELATION_OPERATORS: ReadonlySet<RuleCriteriaOperator> =
101
105
  new Set<RuleCriteriaOperator>([
@@ -295,6 +299,31 @@ class DatabaseService<TBaseModel extends BaseModel> extends BaseService {
295
299
  return data;
296
300
  }
297
301
 
302
+ /*
303
+ * The permission layer's login check, run BEFORE the hooks instead of only
304
+ * after them.
305
+ *
306
+ * The hooks run first, and many of them key off props.userId: a missing one
307
+ * reads as "userId is required" (400), "User should be logged in" (422), or,
308
+ * for Project reads, an empty list with a 200. For an anonymous caller that
309
+ * is almost always a dashboard tab whose access-token cookie expired, and
310
+ * only a 401 makes the browser client refresh the session and replay the
311
+ * request. Everything this admits, the permission check would have admitted
312
+ * too (same condition, same exemptions for API keys and public models), so
313
+ * it only changes which refusal an anonymous caller gets, and it keeps hooks
314
+ * with side effects from running for them at all.
315
+ */
316
+ private checkIfUserIsLoggedInBeforeHooks(
317
+ props: DatabaseCommonInteractionProps,
318
+ type: DatabaseRequestType,
319
+ ): void {
320
+ if (props.isRoot || props.isMasterAdmin) {
321
+ return;
322
+ }
323
+
324
+ PublicPermission.checkIfUserIsLoggedIn(this.modelType, props, type);
325
+ }
326
+
298
327
  protected async onBeforeCreate(
299
328
  createBy: CreateBy<TBaseModel>,
300
329
  ): Promise<OnCreate<TBaseModel>> {
@@ -347,6 +376,49 @@ class DatabaseService<TBaseModel extends BaseModel> extends BaseService {
347
376
  }
348
377
  }
349
378
 
379
+ /*
380
+ * Query operators (StartsWith, NotNull, Search, GreaterThan, Includes...)
381
+ * belong in the `query` of a read/update, never in the `data` of a write.
382
+ * They can reach create/update data because JSONFunctions.deserialize - run
383
+ * on every request body while building the model - turns
384
+ * `{"_type":"StartsWith","value":"a"}` into a real operator instance, and
385
+ * DatabaseBaseModel._fromJSON assigns it to an id/text column unchanged.
386
+ *
387
+ * An operator is never a valid stored value, and leaving one on a write
388
+ * payload also feeds it to the lookups built from that data - the uniqueness
389
+ * check here and the findBy/countBy calls in service hooks - where QueryUtil
390
+ * turns the intended exact comparison into a pattern match, quietly matching
391
+ * rows the caller never named. Refuse such a write up front instead. JSON
392
+ * columns are exempt: they legitimately hold arbitrary objects, and their
393
+ * values are not used to build a query.
394
+ */
395
+ private rejectQueryOperatorsInData(
396
+ data: TBaseModel | PartialEntity<TBaseModel>,
397
+ ): void {
398
+ for (const columnName of Object.keys(data)) {
399
+ const value: unknown = (data as Record<string, unknown>)[columnName];
400
+
401
+ if (!(value instanceof QueryOperator)) {
402
+ continue;
403
+ }
404
+
405
+ if (!this.model.isTableColumn(columnName)) {
406
+ continue;
407
+ }
408
+
409
+ const metadata: TableColumnMetadata =
410
+ this.model.getTableColumnMetadata(columnName);
411
+
412
+ if (metadata && metadata.type === TableColumnType.JSON) {
413
+ continue;
414
+ }
415
+
416
+ throw new BadDataException(
417
+ `Invalid value for ${columnName}. A query operator cannot be used as a value when creating or updating ${this.model.singularName}.`,
418
+ );
419
+ }
420
+ }
421
+
350
422
  /*
351
423
  * Rows written before the fix above hold their ciphertext inside that
352
424
  * HashedString envelope. Decrypting the envelope itself is not just wrong
@@ -984,6 +1056,107 @@ class DatabaseService<TBaseModel extends BaseModel> extends BaseService {
984
1056
  RULE_CRITERIA_LEGACY_NEVER_MATCH_PATTERN;
985
1057
  }
986
1058
 
1059
+ /*
1060
+ * A tenant model declares its tenant TWICE: a scalar column (e.g.
1061
+ * `projectId`) AND a ManyToOne relation (`project`) whose @JoinColumn names
1062
+ * that same scalar. Both are separately writable through the public API, and
1063
+ * both land on the entity that reaches getRepository().save()/update().
1064
+ * TypeORM (metadata/ColumnMetadata.js getEntityValue) resolves the relation
1065
+ * object to the join-column value with PRECEDENCE over the scalar, so a
1066
+ * request carrying `project: { _id: <another project> }` is persisted under
1067
+ * THAT project even though create() has just stamped the scalar to
1068
+ * props.tenantId. That is a cross-tenant write of the whole row (reproduced
1069
+ * end to end: the generated INSERT binds `projectId` to the relation's id,
1070
+ * not the stamped scalar).
1071
+ *
1072
+ * The stamped scalar is the authoritative tenant for every non-root write,
1073
+ * and no `project` relation in the schema legitimately points at a project
1074
+ * other than the tenant (every one joins on `projectId`; there is no second,
1075
+ * foreign-project reference to preserve). So neutralize the relation
1076
+ * spelling: reject a tenant relation that points anywhere other than the
1077
+ * request tenant, then delete it so the scalar is the single source of truth
1078
+ * and no TypeORM precedence rule between the two can move the row. This is
1079
+ * the framework-level generalisation of the per-service fixes already
1080
+ * shipped in ApiKeyPermissionService and UserTelegramService.
1081
+ *
1082
+ * Root / master-admin / internal callers are left untouched — they have no
1083
+ * request tenant (props.tenantId is unset) and legitimately set the tenant
1084
+ * relation for another project during seeding, migrations and
1085
+ * invitation-acceptance. This mirrors the create() scalar stamp, which is
1086
+ * likewise gated on props.tenantId.
1087
+ */
1088
+ private enforceTenantRelationMatchesScalar(
1089
+ data: TBaseModel | PartialEntity<TBaseModel>,
1090
+ props: DatabaseCommonInteractionProps,
1091
+ ): void {
1092
+ if (props.isRoot || props.isMasterAdmin) {
1093
+ return;
1094
+ }
1095
+
1096
+ const tenantColumn: string | null = this.model.getTenantColumn();
1097
+
1098
+ if (!tenantColumn || !props.tenantId) {
1099
+ return;
1100
+ }
1101
+
1102
+ const tenantRelationProperty: string | null =
1103
+ this.getTenantRelationProperty(tenantColumn);
1104
+
1105
+ if (!tenantRelationProperty) {
1106
+ /*
1107
+ * e.g. Project itself, whose tenant column is its own `_id`, has no such
1108
+ * relation; global (non-tenant) models return null from getTenantColumn.
1109
+ */
1110
+ return;
1111
+ }
1112
+
1113
+ const suppliedRelation: unknown = (data as Record<string, unknown>)[
1114
+ tenantRelationProperty
1115
+ ];
1116
+
1117
+ if (suppliedRelation === undefined) {
1118
+ return;
1119
+ }
1120
+
1121
+ const relationTenantId: ObjectID | null = RelationIdUtil.read(
1122
+ data as Record<string, unknown>,
1123
+ [tenantRelationProperty],
1124
+ );
1125
+
1126
+ if (
1127
+ relationTenantId &&
1128
+ relationTenantId.toString() !== props.tenantId.toString()
1129
+ ) {
1130
+ throw new BadDataException(
1131
+ `The ${tenantRelationProperty} relation does not belong to this project.`,
1132
+ );
1133
+ }
1134
+
1135
+ delete (data as Record<string, unknown>)[tenantRelationProperty];
1136
+ }
1137
+
1138
+ /*
1139
+ * Property name of the ManyToOne relation that shares the tenant scalar
1140
+ * column as its join column (`project` for the `projectId` tenant column),
1141
+ * or null when the model has no such relation.
1142
+ */
1143
+ private getTenantRelationProperty(tenantColumn: string): string | null {
1144
+ for (const columnName of this.model.getTableColumns().columns) {
1145
+ const metadata: TableColumnMetadata | undefined =
1146
+ this.model.getTableColumnMetadata(columnName);
1147
+
1148
+ if (
1149
+ metadata &&
1150
+ metadata.type === TableColumnType.Entity &&
1151
+ metadata.manyToOneRelationColumn === tenantColumn
1152
+ ) {
1153
+ return columnName;
1154
+ }
1155
+ }
1156
+
1157
+ return null;
1158
+ }
1159
+
987
1160
  private async sanitizeCreateOrUpdate(
988
1161
  data: TBaseModel | PartialEntity<TBaseModel>,
989
1162
  props: DatabaseCommonInteractionProps,
@@ -1368,6 +1541,34 @@ class DatabaseService<TBaseModel extends BaseModel> extends BaseService {
1368
1541
 
1369
1542
  @CaptureSpan()
1370
1543
  public async create(createBy: CreateBy<TBaseModel>): Promise<TBaseModel> {
1544
+ this.checkIfUserIsLoggedInBeforeHooks(
1545
+ createBy.props,
1546
+ DatabaseRequestType.Create,
1547
+ );
1548
+
1549
+ /*
1550
+ * A non-root create must not pin the row's own primary key. save() treats
1551
+ * an entity carrying an existing id as an update of that row rather than an
1552
+ * insert, so a supplied `_id` turns a create into an in-place modification
1553
+ * of a record the caller never named. BaseAPI.createItem already strips it;
1554
+ * this guards every other non-root caller (custom routes, workflow
1555
+ * components) too. Root/internal seeding legitimately assigns ids and is
1556
+ * exempt. Only the top-level primary key is checked - nested relation
1557
+ * `_id`s reference existing related rows and are fine.
1558
+ */
1559
+ if (
1560
+ !createBy.props.isRoot &&
1561
+ !createBy.props.isMasterAdmin &&
1562
+ (createBy.data as TBaseModel)._id
1563
+ ) {
1564
+ throw new BadDataException(
1565
+ `An id cannot be supplied when creating ${this.model.singularName}.`,
1566
+ );
1567
+ }
1568
+
1569
+ // Query operators are for queries, not for write payloads. See the helper.
1570
+ this.rejectQueryOperatorsInData(createBy.data);
1571
+
1371
1572
  this.unwrapHashedStringsForUnhashedColumns(createBy.data);
1372
1573
 
1373
1574
  const onCreate: OnCreate<TBaseModel> = createBy.props.ignoreHooks
@@ -1389,6 +1590,15 @@ class DatabaseService<TBaseModel extends BaseModel> extends BaseService {
1389
1590
  data.setColumnValue(tenantColumnName, _createdBy.props.tenantId);
1390
1591
  }
1391
1592
 
1593
+ /*
1594
+ * The tenant scalar has just been stamped to the request tenant, but the
1595
+ * matching tenant RELATION object (e.g. `project`) is still whatever the
1596
+ * caller sent, and TypeORM lets that relation override the scalar on the
1597
+ * INSERT. Force the relation to agree with — or be dropped in favour of —
1598
+ * the stamped scalar so a caller cannot write the row into another tenant.
1599
+ */
1600
+ this.enforceTenantRelationMatchesScalar(data, _createdBy.props);
1601
+
1392
1602
  data = this.generateDefaultValues(data);
1393
1603
 
1394
1604
  data = this.checkRequiredFields(data);
@@ -2291,6 +2501,11 @@ class DatabaseService<TBaseModel extends BaseModel> extends BaseService {
2291
2501
  @CaptureSpan()
2292
2502
  public async hardDeleteBy(deleteBy: DeleteBy<TBaseModel>): Promise<number> {
2293
2503
  try {
2504
+ this.checkIfUserIsLoggedInBeforeHooks(
2505
+ deleteBy.props,
2506
+ DatabaseRequestType.Delete,
2507
+ );
2508
+
2294
2509
  const onDelete: OnDelete<TBaseModel> = deleteBy.props.ignoreHooks
2295
2510
  ? { deleteBy, carryForward: [] }
2296
2511
  : await this.onBeforeDelete(deleteBy);
@@ -2353,6 +2568,11 @@ class DatabaseService<TBaseModel extends BaseModel> extends BaseService {
2353
2568
  try {
2354
2569
  this.setTelemetryContextFromProps(deleteBy.props);
2355
2570
 
2571
+ this.checkIfUserIsLoggedInBeforeHooks(
2572
+ deleteBy.props,
2573
+ DatabaseRequestType.Delete,
2574
+ );
2575
+
2356
2576
  if (this.doNotAllowDelete && !deleteBy.props.isRoot) {
2357
2577
  throw new BadDataException("Delete not allowed");
2358
2578
  }
@@ -2587,6 +2807,11 @@ class DatabaseService<TBaseModel extends BaseModel> extends BaseService {
2587
2807
  try {
2588
2808
  this.setTelemetryContextFromProps(findBy.props);
2589
2809
 
2810
+ this.checkIfUserIsLoggedInBeforeHooks(
2811
+ findBy.props,
2812
+ DatabaseRequestType.Read,
2813
+ );
2814
+
2590
2815
  if (!findBy.sort || Object.keys(findBy.sort).length === 0) {
2591
2816
  findBy.sort = {
2592
2817
  createdAt: SortOrder.Descending,
@@ -2967,8 +3192,28 @@ class DatabaseService<TBaseModel extends BaseModel> extends BaseService {
2967
3192
  try {
2968
3193
  this.setTelemetryContextFromProps(updateBy.props);
2969
3194
 
3195
+ this.checkIfUserIsLoggedInBeforeHooks(
3196
+ updateBy.props,
3197
+ DatabaseRequestType.Update,
3198
+ );
3199
+
2970
3200
  updateBy.data = this.sanitizeUpdateData(updateBy.data);
2971
3201
 
3202
+ // Query operators are for queries, not for write payloads. See the helper.
3203
+ this.rejectQueryOperatorsInData(updateBy.data);
3204
+
3205
+ /*
3206
+ * Defense in depth for the tenant confused-deputy on the update path.
3207
+ * Unlike create(), _updateBy() never re-stamps the tenant scalar, and a
3208
+ * tenant relation object would likewise override the scalar join column
3209
+ * on the UPDATE. Today the tenant columns carry `update: []` so the
3210
+ * column-permission check rejects them first, but that is incidental —
3211
+ * this keeps the row's tenant immutable even if a model ever grants
3212
+ * update on the tenant relation. Runs before the permission check so the
3213
+ * ACL stays a redundant second line rather than the only one.
3214
+ */
3215
+ this.enforceTenantRelationMatchesScalar(updateBy.data, updateBy.props);
3216
+
2972
3217
  this.unwrapHashedStringsForUnhashedColumns(updateBy.data);
2973
3218
 
2974
3219
  const onUpdate: OnUpdate<TBaseModel> = updateBy.props.ignoreHooks
@@ -5,6 +5,8 @@ import UpdateBy from "../Types/Database/UpdateBy";
5
5
  import { OnCreate, OnUpdate } from "../Types/Database/Hooks";
6
6
  import BadDataException from "../../Types/Exception/BadDataException";
7
7
  import {
8
+ DETECTION_EVALUATION_INTERVAL_MAX_IN_MINUTES,
9
+ DETECTION_EVALUATION_INTERVAL_MIN_IN_MINUTES,
8
10
  DETECTION_MATCH_COUNT_THRESHOLD_MAX,
9
11
  DETECTION_MATCH_COUNT_THRESHOLD_MIN,
10
12
  } from "../../Types/SecurityEvent/DetectionFindingConstants";
@@ -52,10 +54,9 @@ export class Service extends DatabaseService<Model> {
52
54
  private validateEvaluationInterval(interval: number | undefined): void {
53
55
  this.validateIntegerInRange({
54
56
  value: interval,
55
- min: 1,
56
- max: 1440,
57
- message:
58
- "Evaluation interval must be a whole number of minutes between 1 and 1440.",
57
+ min: DETECTION_EVALUATION_INTERVAL_MIN_IN_MINUTES,
58
+ max: DETECTION_EVALUATION_INTERVAL_MAX_IN_MINUTES,
59
+ message: `Evaluation interval must be a whole number of minutes between ${DETECTION_EVALUATION_INTERVAL_MIN_IN_MINUTES} and ${DETECTION_EVALUATION_INTERVAL_MAX_IN_MINUTES}.`,
59
60
  });
60
61
  }
61
62