@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,259 @@
1
+ import Incident from "../../../Models/DatabaseModels/Incident";
2
+ import Monitor from "../../../Models/DatabaseModels/Monitor";
3
+ import Project from "../../../Models/DatabaseModels/Project";
4
+ import IncidentService from "../../../Server/Services/IncidentService";
5
+ import MonitorService from "../../../Server/Services/MonitorService";
6
+ import DatabaseCommonInteractionProps from "../../../Types/BaseDatabase/DatabaseCommonInteractionProps";
7
+ import BadDataException from "../../../Types/Exception/BadDataException";
8
+ import ObjectID from "../../../Types/ObjectID";
9
+ import Permission, { UserPermission } from "../../../Types/Permission";
10
+ import PositiveNumber from "../../../Types/PositiveNumber";
11
+ import { getJestSpyOn } from "../../Spy";
12
+ import {
13
+ afterEach,
14
+ beforeEach,
15
+ describe,
16
+ expect,
17
+ jest,
18
+ test,
19
+ } from "@jest/globals";
20
+
21
+ /*
22
+ * PasswordHash has a known TS5.9 compile failure under ts-jest that breaks any
23
+ * suite whose import graph reaches it (see ApiKeyPermissionSecurity.test.ts).
24
+ * Nothing here touches password hashing; stub it before the service import
25
+ * graph drags it into compilation.
26
+ */
27
+ jest.mock("../../../Server/Utils/PasswordHash", () => {
28
+ return {
29
+ __esModule: true,
30
+ default: class PasswordHashStub {},
31
+ };
32
+ });
33
+
34
+ /*
35
+ * Cross-tenant write via the tenant RELATION (confused deputy).
36
+ *
37
+ * A tenant model declares its tenant twice — the scalar `projectId` column and
38
+ * the `project` @ManyToOne relation joined on that same column — and both are
39
+ * writable by an ordinary member on create. `DatabaseService.create` stamps
40
+ * only the scalar to `props.tenantId`; TypeORM then lets the relation object
41
+ * override the scalar join value on the INSERT, so a member of project A who
42
+ * posts `project: { _id: B }` writes the row into project B.
43
+ *
44
+ * `enforceTenantRelationMatchesScalar` rejects a tenant relation pointing at a
45
+ * different project and deletes it so the stamped scalar is the only thing
46
+ * that reaches the database. These tests drive the real `create()` pipeline
47
+ * (only the IO/validation neighbours that are orthogonal to tenancy are
48
+ * stubbed) and the guard directly for the update-shaped (plain object) input.
49
+ */
50
+
51
+ const PROJECT_A: ObjectID = new ObjectID(
52
+ "aaaaaaaa-aaaa-4aaa-8aaa-aaaaaaaaaaaa",
53
+ );
54
+ const PROJECT_B: ObjectID = new ObjectID(
55
+ "bbbbbbbb-bbbb-4bbb-8bbb-bbbbbbbbbbbb",
56
+ );
57
+
58
+ function userPermission(permission: Permission): UserPermission {
59
+ return {
60
+ permission,
61
+ labelIds: [],
62
+ isBlockPermission: false,
63
+ _type: "UserPermission",
64
+ };
65
+ }
66
+
67
+ function memberProps(
68
+ tenantId: ObjectID = PROJECT_A,
69
+ ): DatabaseCommonInteractionProps {
70
+ return {
71
+ userId: new ObjectID("dddddddd-dddd-4ddd-8ddd-dddddddddddd"),
72
+ tenantId,
73
+ ignoreHooks: true,
74
+ userGlobalAccessPermission: {
75
+ projectIds: [tenantId],
76
+ globalPermissions: [Permission.Public, Permission.User],
77
+ _type: "UserGlobalAccessPermission",
78
+ },
79
+ userTenantAccessPermission: {
80
+ [tenantId.toString()]: {
81
+ projectId: tenantId,
82
+ permissions: [userPermission(Permission.ProjectMember)],
83
+ _type: "UserTenantAccessPermission",
84
+ },
85
+ },
86
+ };
87
+ }
88
+
89
+ function rootProps(): DatabaseCommonInteractionProps {
90
+ return { isRoot: true, ignoreHooks: true };
91
+ }
92
+
93
+ type Target = {
94
+ name: string;
95
+ service: typeof MonitorService | typeof IncidentService;
96
+ build: () => Monitor | Incident;
97
+ };
98
+
99
+ const TARGETS: Array<Target> = [
100
+ {
101
+ name: "Monitor",
102
+ service: MonitorService,
103
+ build: () => {
104
+ const monitor: Monitor = new Monitor();
105
+ monitor.name = "guard-test";
106
+ return monitor;
107
+ },
108
+ },
109
+ {
110
+ name: "Incident",
111
+ service: IncidentService,
112
+ build: () => {
113
+ const incident: Incident = new Incident();
114
+ incident.title = "guard-test";
115
+ return incident;
116
+ },
117
+ },
118
+ ];
119
+
120
+ function projectRelation(id: ObjectID): Project {
121
+ const project: Project = new Project();
122
+ project._id = id.toString();
123
+ return project;
124
+ }
125
+
126
+ describe("DatabaseService tenant-relation cross-tenant write guard", () => {
127
+ describe.each(TARGETS)("$name create()", (target: Target) => {
128
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
129
+ const service: any = target.service;
130
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
131
+ let save: jest.Mock<(entity: any) => Promise<any>>;
132
+
133
+ beforeEach(() => {
134
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
135
+ save = jest.fn(async (entity: any) => {
136
+ return entity;
137
+ }) as any;
138
+ getJestSpyOn(service, "getRepository").mockReturnValue({
139
+ save,
140
+ } as never);
141
+ // Count-backed validators (unique/limit checks) must not hit Postgres.
142
+ getJestSpyOn(service, "countBy").mockResolvedValue(
143
+ new PositiveNumber(0) as never,
144
+ );
145
+ /*
146
+ * Required-field validation is orthogonal to the tenancy guard under
147
+ * test; keep it from failing on unrelated columns.
148
+ */
149
+ getJestSpyOn(service, "checkRequiredFields").mockImplementation(((
150
+ data: unknown,
151
+ ) => {
152
+ return data;
153
+ }) as never);
154
+ // Fire-and-forget side effects that would otherwise reach the network.
155
+ getJestSpyOn(service, "onTriggerWorkflow").mockResolvedValue(
156
+ undefined as never,
157
+ );
158
+ getJestSpyOn(service, "onTriggerRealtime").mockResolvedValue(
159
+ undefined as never,
160
+ );
161
+ });
162
+
163
+ afterEach(() => {
164
+ jest.restoreAllMocks();
165
+ });
166
+
167
+ test("rejects a create whose project relation points at another project", async () => {
168
+ const data: Monitor | Incident = target.build();
169
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
170
+ (data as any).project = projectRelation(PROJECT_B);
171
+
172
+ await expect(
173
+ service.create({ data, props: memberProps(PROJECT_A) }),
174
+ ).rejects.toThrow(BadDataException);
175
+
176
+ expect(save).not.toHaveBeenCalled();
177
+ });
178
+
179
+ test("drops a matching project relation and persists under the request tenant only", async () => {
180
+ const data: Monitor | Incident = target.build();
181
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
182
+ (data as any).project = projectRelation(PROJECT_A);
183
+
184
+ await service.create({ data, props: memberProps(PROJECT_A) });
185
+
186
+ expect(save).toHaveBeenCalledTimes(1);
187
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
188
+ const saved: any = save.mock.calls[0]![0];
189
+ expect(saved.project).toBeUndefined();
190
+ expect(saved.projectId?.toString()).toBe(PROJECT_A.toString());
191
+ });
192
+
193
+ test("leaves the project relation untouched for a root/internal caller", async () => {
194
+ const data: Monitor | Incident = target.build();
195
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
196
+ (data as any).project = projectRelation(PROJECT_B);
197
+
198
+ await service.create({ data, props: rootProps() });
199
+
200
+ expect(save).toHaveBeenCalledTimes(1);
201
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
202
+ const saved: any = save.mock.calls[0]![0];
203
+ expect(saved.project).toBeInstanceOf(Project);
204
+ expect(saved.project._id).toBe(PROJECT_B.toString());
205
+ });
206
+ });
207
+
208
+ /*
209
+ * The same guard runs on the update path, where the payload is a plain
210
+ * object (BaseAPI.updateItem deserializes rather than fromJSON'ing), so the
211
+ * relation arrives as `{ _id: ... }` rather than a Project instance.
212
+ */
213
+ describe("enforceTenantRelationMatchesScalar (update-shaped input)", () => {
214
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
215
+ const guard: any = MonitorService;
216
+
217
+ test("throws when a plain-object project relation points at another project", () => {
218
+ const data: Record<string, unknown> = {
219
+ name: "x",
220
+ project: { _id: PROJECT_B.toString() },
221
+ };
222
+
223
+ expect(() => {
224
+ guard.enforceTenantRelationMatchesScalar(data, memberProps(PROJECT_A));
225
+ }).toThrow(BadDataException);
226
+ });
227
+
228
+ test("strips a matching plain-object project relation", () => {
229
+ const data: Record<string, unknown> = {
230
+ name: "x",
231
+ project: { _id: PROJECT_A.toString() },
232
+ };
233
+
234
+ guard.enforceTenantRelationMatchesScalar(data, memberProps(PROJECT_A));
235
+
236
+ expect(data["project"]).toBeUndefined();
237
+ expect(data["name"]).toBe("x");
238
+ });
239
+
240
+ test("is a no-op when no project relation is supplied", () => {
241
+ const data: Record<string, unknown> = { name: "x" };
242
+
243
+ expect(() => {
244
+ guard.enforceTenantRelationMatchesScalar(data, memberProps(PROJECT_A));
245
+ }).not.toThrow();
246
+ expect(data).toEqual({ name: "x" });
247
+ });
248
+
249
+ test("does not touch the relation for a root/internal caller", () => {
250
+ const data: Record<string, unknown> = {
251
+ project: { _id: PROJECT_B.toString() },
252
+ };
253
+
254
+ guard.enforceTenantRelationMatchesScalar(data, rootProps());
255
+
256
+ expect(data["project"]).toEqual({ _id: PROJECT_B.toString() });
257
+ });
258
+ });
259
+ });
@@ -0,0 +1,147 @@
1
+ import ProbeService from "../../../Server/Services/ProbeService";
2
+ import CreateBy from "../../../Server/Types/Database/CreateBy";
3
+ import BaseModel from "../../../Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel";
4
+ import Probe from "../../../Models/DatabaseModels/Probe";
5
+ import StartsWith from "../../../Types/BaseDatabase/StartsWith";
6
+ import NotNull from "../../../Types/BaseDatabase/NotNull";
7
+ import DatabaseCommonInteractionProps from "../../../Types/BaseDatabase/DatabaseCommonInteractionProps";
8
+ import BadDataException from "../../../Types/Exception/BadDataException";
9
+ import { JSONObject } from "../../../Types/JSON";
10
+ import ObjectID from "../../../Types/ObjectID";
11
+ import Permission, {
12
+ UserPermission,
13
+ UserTenantAccessPermission,
14
+ } from "../../../Types/Permission";
15
+ import UserType from "../../../Types/UserType";
16
+ import { afterEach, describe, expect, jest, test } from "@jest/globals";
17
+
18
+ /*
19
+ * Query operators belong in the `query` of a read/update, never in the `data`
20
+ * of a write. A request value shaped like a serialized operator, e.g.
21
+ * {"_type":"StartsWith","value":"a"} or {"_type":"NotNull"}, becomes a real
22
+ * operator instance: JSONFunctions.deserialize runs on every request body while
23
+ * DatabaseBaseModel._fromJSON builds the model, and the operator is assigned to
24
+ * the column unchanged.
25
+ *
26
+ * An operator is never a valid stored value, and one left on a write payload is
27
+ * also fed to the lookups built from that data (the uniqueness check, service
28
+ * hooks), where it turns an intended exact comparison into a pattern match.
29
+ * DatabaseService rejects such a write up front, before any hook or query runs.
30
+ * JSON columns are exempt - they legitimately hold arbitrary objects.
31
+ *
32
+ * The first two tests document the deserialization behaviour, which is
33
+ * unchanged; the last two pin the rejection and that ordinary writes still pass.
34
+ */
35
+
36
+ const PROJECT_ID: ObjectID = new ObjectID(
37
+ "00000000-0000-4000-8000-00000000000a",
38
+ );
39
+
40
+ const memberProps: (
41
+ permissions: Array<Permission>,
42
+ ) => DatabaseCommonInteractionProps = (
43
+ permissions: Array<Permission>,
44
+ ): DatabaseCommonInteractionProps => {
45
+ const tenantPermission: UserTenantAccessPermission = {
46
+ projectId: PROJECT_ID,
47
+ _type: "UserTenantAccessPermission",
48
+ permissions: permissions.map((permission: Permission): UserPermission => {
49
+ return {
50
+ _type: "UserPermission",
51
+ permission: permission,
52
+ labelIds: [],
53
+ isBlockPermission: false,
54
+ };
55
+ }),
56
+ };
57
+
58
+ return {
59
+ userId: new ObjectID("00000000-0000-4000-8000-000000000003"),
60
+ tenantId: PROJECT_ID,
61
+ userType: UserType.User,
62
+ userTenantAccessPermission: {
63
+ [PROJECT_ID.toString()]: tenantPermission,
64
+ },
65
+ };
66
+ };
67
+
68
+ afterEach(() => {
69
+ jest.restoreAllMocks();
70
+ });
71
+
72
+ describe("Query operators supplied as write values", () => {
73
+ test("request body value {_type:StartsWith} deserializes into a StartsWith on a text column", () => {
74
+ const body: JSONObject = {
75
+ key: { _type: "StartsWith", value: "a" } as unknown as JSONObject,
76
+ name: "a probe",
77
+ };
78
+
79
+ const probe: Probe = BaseModel.fromJSON<Probe>(body, Probe) as Probe;
80
+
81
+ expect(probe.key).toBeInstanceOf(StartsWith);
82
+ expect((probe.key as unknown as StartsWith<string>).toString()).toBe("a");
83
+ });
84
+
85
+ test("request body value {_type:NotNull} deserializes into a NotNull operator", () => {
86
+ const body: JSONObject = {
87
+ key: { _type: "NotNull" } as unknown as JSONObject,
88
+ };
89
+
90
+ const probe: Probe = BaseModel.fromJSON<Probe>(body, Probe) as Probe;
91
+ expect(probe.key).toBeInstanceOf(NotNull);
92
+ });
93
+
94
+ test("DatabaseService.create rejects an operator in write data before any lookup", async () => {
95
+ /*
96
+ * If the check regresses, the uniqueness check would run its countBy with
97
+ * the operator in the query; make that fail loudly instead.
98
+ */
99
+ const countSpy: jest.SpyInstance = jest
100
+ .spyOn(ProbeService, "countBy")
101
+ .mockImplementation((() => {
102
+ throw new Error("countBy must not run for an operator-carrying create");
103
+ }) as never) as unknown as jest.SpyInstance;
104
+ const hookSpy: jest.SpyInstance = jest.spyOn(
105
+ ProbeService,
106
+ "onBeforeCreate" as never,
107
+ ) as unknown as jest.SpyInstance;
108
+
109
+ const probe: Probe = new Probe();
110
+ (probe as unknown as { key: unknown }).key = new StartsWith("a");
111
+ probe.name = "a probe";
112
+
113
+ const createBy: CreateBy<Probe> = {
114
+ data: probe,
115
+ props: memberProps([Permission.CreateProjectProbe]),
116
+ };
117
+
118
+ await expect(ProbeService.create(createBy)).rejects.toBeInstanceOf(
119
+ BadDataException,
120
+ );
121
+ expect(hookSpy).not.toHaveBeenCalled();
122
+ expect(countSpy).not.toHaveBeenCalled();
123
+ });
124
+
125
+ test("the operator check leaves an ordinary create untouched", () => {
126
+ /*
127
+ * The check must refuse operators without touching plain values. Call it
128
+ * directly - it is the choke point create()/update() run - and assert a
129
+ * normal payload passes while an operator is refused.
130
+ */
131
+ const legit: Probe = new Probe();
132
+ legit.key = "a-real-plaintext-key";
133
+ legit.name = "a probe";
134
+
135
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
136
+ const service: any = ProbeService as any;
137
+ expect(() => {
138
+ service.rejectQueryOperatorsInData(legit);
139
+ }).not.toThrow();
140
+
141
+ const withOperator: Probe = new Probe();
142
+ (withOperator as unknown as { key: unknown }).key = new StartsWith("a");
143
+ expect(() => {
144
+ service.rejectQueryOperatorsInData(withOperator);
145
+ }).toThrow(BadDataException);
146
+ });
147
+ });
@@ -2,15 +2,19 @@ import MonitorService from "../../../Server/Services/MonitorService";
2
2
  import MonitorStatusService from "../../../Server/Services/MonitorStatusService";
3
3
  import ProjectService from "../../../Server/Services/ProjectService";
4
4
  import PayAsYouGoBillingService from "../../../Server/Services/PayAsYouGoBillingService";
5
+ import BillingService from "../../../Server/Services/BillingService";
5
6
  import MonitorStepsProjectValidator from "../../../Server/Utils/Monitor/MonitorStepsProjectValidator";
6
7
  import Monitor from "../../../Models/DatabaseModels/Monitor";
7
8
  import MonitorStatus from "../../../Models/DatabaseModels/MonitorStatus";
9
+ import Project from "../../../Models/DatabaseModels/Project";
8
10
  import CreateBy from "../../../Server/Types/Database/CreateBy";
9
11
  import UpdateBy from "../../../Server/Types/Database/UpdateBy";
10
12
  import MonitorType from "../../../Types/Monitor/MonitorType";
11
13
  import ObjectID from "../../../Types/ObjectID";
12
14
  import PositiveNumber from "../../../Types/PositiveNumber";
13
- import { PlanType } from "../../../Types/Billing/SubscriptionPlan";
15
+ import SubscriptionPlan, {
16
+ PlanType,
17
+ } from "../../../Types/Billing/SubscriptionPlan";
14
18
  import PaymentRequiredException from "../../../Types/Exception/PaymentRequiredException";
15
19
  import * as EnvironmentConfig from "../../../Server/EnvironmentConfig";
16
20
  import {
@@ -89,6 +93,30 @@ function expectPaymentCheckedFor(project: ObjectID): void {
89
93
  }
90
94
  }
91
95
 
96
+ function useRealPaymentEligibility(plan: PlanType): void {
97
+ jest.mocked(PayAsYouGoBillingService.canUsePayAsYouGo).mockRestore();
98
+ PayAsYouGoBillingService.invalidate(projectId);
99
+ PayAsYouGoBillingService.invalidate(otherProjectId);
100
+ jest.spyOn(BillingService, "isBillingEnabled").mockReturnValue(true);
101
+ jest.spyOn(BillingService, "hasPaymentMethods").mockResolvedValue(false);
102
+ jest.spyOn(BillingService, "getSubscription");
103
+ jest.spyOn(ProjectService, "findOneById").mockResolvedValue(
104
+ Object.assign(new Project(), {
105
+ paymentProviderPlanId: plan,
106
+ paymentProviderCustomerId: "cus_monitor_project",
107
+ }),
108
+ );
109
+ jest
110
+ .spyOn(SubscriptionPlan, "getSubscriptionPlanById")
111
+ .mockReturnValue(
112
+ new SubscriptionPlan(plan, `${plan}_yearly`, plan, 0, 0, 0, 0),
113
+ );
114
+ jest.spyOn(ProjectService, "getCurrentPlan").mockResolvedValue({
115
+ plan,
116
+ isSubscriptionUnpaid: false,
117
+ });
118
+ }
119
+
92
120
  beforeEach(() => {
93
121
  jest.restoreAllMocks();
94
122
  (EnvironmentConfig as { IsBillingEnabled: boolean }).IsBillingEnabled = true;
@@ -300,3 +328,89 @@ describe("monitor update payment admission", () => {
300
328
  expect(MonitorService.findBy).not.toHaveBeenCalled();
301
329
  });
302
330
  });
331
+
332
+ describe("monitor operations use the stored subscription plan for payment eligibility", () => {
333
+ test.each([PlanType.Growth, PlanType.Scale, PlanType.Enterprise])(
334
+ "allows active monitor creation on %s without a payment method",
335
+ async (plan: PlanType) => {
336
+ useRealPaymentEligibility(plan);
337
+
338
+ await expect(
339
+ hooks.onBeforeCreate(createInput(MonitorType.Website)),
340
+ ).resolves.toBeDefined();
341
+
342
+ expect(ProjectService.findOneById).toHaveBeenCalledWith(
343
+ expect.objectContaining({ id: projectId }),
344
+ );
345
+ expect(BillingService.hasPaymentMethods).not.toHaveBeenCalled();
346
+ expect(BillingService.getSubscription).not.toHaveBeenCalled();
347
+ expect(MonitorService.countBy).not.toHaveBeenCalled();
348
+ },
349
+ );
350
+
351
+ describe.each([PlanType.Growth, PlanType.Scale, PlanType.Enterprise])(
352
+ "%s monitor updates without a payment method",
353
+ (plan: PlanType) => {
354
+ test.each([
355
+ { disableActiveMonitoring: false },
356
+ { monitorType: MonitorType.API },
357
+ ])(
358
+ "allows the billable update %j",
359
+ async (data: UpdateBy<Monitor>["data"]) => {
360
+ useRealPaymentEligibility(plan);
361
+ jest
362
+ .spyOn(MonitorService, "findBy")
363
+ .mockResolvedValue([
364
+ storedMonitor(otherProjectId, MonitorType.Website),
365
+ ]);
366
+
367
+ await expect(
368
+ hooks.onBeforeUpdate(updateInput(data)),
369
+ ).resolves.toBeDefined();
370
+
371
+ expect(ProjectService.findOneById).toHaveBeenCalledWith(
372
+ expect.objectContaining({ id: otherProjectId }),
373
+ );
374
+ expect(BillingService.hasPaymentMethods).not.toHaveBeenCalled();
375
+ },
376
+ );
377
+ },
378
+ );
379
+
380
+ test("still rejects Free monitor creation and re-enabling without a payment method", async () => {
381
+ useRealPaymentEligibility(PlanType.Free);
382
+ jest
383
+ .spyOn(MonitorService, "findBy")
384
+ .mockResolvedValue([storedMonitor(projectId, MonitorType.Website)]);
385
+
386
+ await expect(
387
+ hooks.onBeforeCreate(createInput(MonitorType.Website)),
388
+ ).rejects.toBeInstanceOf(PaymentRequiredException);
389
+ await expect(
390
+ hooks.onBeforeUpdate(updateInput({ disableActiveMonitoring: false })),
391
+ ).rejects.toBeInstanceOf(PaymentRequiredException);
392
+
393
+ expect(BillingService.hasPaymentMethods).toHaveBeenCalledWith(
394
+ "cus_monitor_project",
395
+ );
396
+ expect(MonitorStatusService.findOneBy).not.toHaveBeenCalled();
397
+ });
398
+
399
+ test.each([PlanType.Growth, PlanType.Scale, PlanType.Enterprise])(
400
+ "retains the separate unpaid %s subscription check after exempting payment setup",
401
+ async (plan: PlanType) => {
402
+ useRealPaymentEligibility(plan);
403
+ jest.spyOn(ProjectService, "getCurrentPlan").mockResolvedValue({
404
+ plan,
405
+ isSubscriptionUnpaid: true,
406
+ });
407
+
408
+ await expect(
409
+ hooks.onBeforeCreate(createInput(MonitorType.Website)),
410
+ ).rejects.toThrow("subscription is unpaid");
411
+
412
+ expect(BillingService.hasPaymentMethods).not.toHaveBeenCalled();
413
+ expect(MonitorStatusService.findOneBy).not.toHaveBeenCalled();
414
+ },
415
+ );
416
+ });