@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,394 @@
1
+ import BaseModel from "../../../Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel";
2
+ import Entities from "../../../Models/DatabaseModels/Index";
3
+ import TeamMember from "../../../Models/DatabaseModels/TeamMember";
4
+ import BaseAPI from "../../../Server/API/BaseAPI";
5
+ import PostgresAppInstance from "../../../Server/Infrastructure/PostgresDatabase";
6
+ import DatabaseService from "../../../Server/Services/DatabaseService";
7
+ import Select from "../../../Server/Types/Database/Select";
8
+ import {
9
+ ExpressResponse,
10
+ OneUptimeRequest,
11
+ } from "../../../Server/Utils/Express";
12
+ import DatabaseCommonInteractionProps from "../../../Types/BaseDatabase/DatabaseCommonInteractionProps";
13
+ import { JSONObject } from "../../../Types/JSON";
14
+ import JSONFunctions from "../../../Types/JSONFunctions";
15
+ import ObjectID from "../../../Types/ObjectID";
16
+ import Permission from "../../../Types/Permission";
17
+ import UserType from "../../../Types/UserType";
18
+ import { DataSource } from "typeorm";
19
+
20
+ /*
21
+ * The handler receives an already-authenticated request and uses a dedicated
22
+ * DataSource below. Avoid loading unrelated login, billing, and boot-migration
23
+ * services; no permission check, repository operation, or serializer is mocked.
24
+ */
25
+ jest.mock("../../../Server/Middleware/UserAuthorization", () => {
26
+ return { getUserMiddleware: jest.fn() };
27
+ });
28
+ jest.mock("../../../Server/Services/ProjectService", () => {
29
+ return { getCurrentPlan: jest.fn() };
30
+ });
31
+ jest.mock("../../../Server/Infrastructure/Postgres/DataSourceOptions", () => {
32
+ return {};
33
+ });
34
+
35
+ /*
36
+ * Opt in with RUN_POSTGRES_TEAM_MEMBER_PERMISSION_TESTS=true and config.env.
37
+ * Only table definitions are copied from public. Every row is synthetic and
38
+ * every read/write is directed to an isolated schema that is removed below.
39
+ * The permission pipeline, request-header translation, TypeORM joins, and
40
+ * response serialization run unchanged.
41
+ */
42
+ const describePostgres: typeof describe =
43
+ process.env["RUN_POSTGRES_TEAM_MEMBER_PERMISSION_TESTS"] === "true"
44
+ ? describe
45
+ : describe.skip;
46
+
47
+ describePostgres(
48
+ "multi-tenant team-member read authorization against Postgres",
49
+ () => {
50
+ const schema: string = `team_member_permission_test_${ObjectID.generate().toString().replace(/-/g, "")}`;
51
+ const userId: ObjectID = ObjectID.generate();
52
+ const otherUserId: ObjectID = ObjectID.generate();
53
+ const inviterId: ObjectID = ObjectID.generate();
54
+ const firstProjectId: ObjectID = ObjectID.generate();
55
+ const secondProjectId: ObjectID = ObjectID.generate();
56
+ const firstTeamId: ObjectID = ObjectID.generate();
57
+ const secondTeamId: ObjectID = ObjectID.generate();
58
+ const firstInvitationId: ObjectID = ObjectID.generate();
59
+ const secondInvitationId: ObjectID = ObjectID.generate();
60
+ const otherInvitationId: ObjectID = ObjectID.generate();
61
+ const acceptedMembershipId: ObjectID = ObjectID.generate();
62
+ const passwordHash: string = "synthetic-inviter-password-hash";
63
+ const resetToken: string = "synthetic-inviter-reset-token";
64
+ const privateTeamDescription: string = "Synthetic private team description";
65
+ const service: DatabaseService<TeamMember> = new DatabaseService(
66
+ TeamMember,
67
+ );
68
+ const api: BaseAPI<TeamMember, DatabaseService<TeamMember>> = new BaseAPI(
69
+ TeamMember,
70
+ service,
71
+ );
72
+ let database: DataSource;
73
+
74
+ beforeAll(async () => {
75
+ database = new DataSource({
76
+ type: "postgres",
77
+ host:
78
+ process.env["TEAM_MEMBER_PERMISSION_TEST_DATABASE_HOST"] ||
79
+ "localhost",
80
+ port: Number(
81
+ process.env["TEAM_MEMBER_PERMISSION_TEST_DATABASE_PORT"] || "5400",
82
+ ),
83
+ username: process.env["DATABASE_USERNAME"] || "postgres",
84
+ password: process.env["DATABASE_PASSWORD"] || "password",
85
+ database: process.env["DATABASE_NAME"] || "oneuptimedb",
86
+ entities: Entities,
87
+ schema,
88
+ synchronize: false,
89
+ extra: { options: `-c search_path=${schema},public` },
90
+ });
91
+ await database.initialize();
92
+ await database.query(`CREATE SCHEMA "${schema}"`);
93
+ for (const table of ["User", "Project", "Team", "TeamMember"]) {
94
+ await database.query(
95
+ `CREATE TABLE "${schema}"."${table}" (LIKE public."${table}" INCLUDING ALL)`,
96
+ );
97
+ }
98
+ jest.spyOn(PostgresAppInstance, "isConnected").mockReturnValue(true);
99
+ jest
100
+ .spyOn(PostgresAppInstance, "getDataSource")
101
+ .mockReturnValue(database);
102
+
103
+ for (const id of [userId, otherUserId, inviterId]) {
104
+ await database.query(
105
+ `INSERT INTO "${schema}"."User"
106
+ ("_id", "name", "email", "slug", "password", "resetPasswordToken", "version")
107
+ VALUES ($1, 'Synthetic User', $2, $3, $4, $5, 1)`,
108
+ [
109
+ id.toString(),
110
+ `${id.toString()}@example.com`,
111
+ id.toString(),
112
+ passwordHash,
113
+ resetToken,
114
+ ],
115
+ );
116
+ }
117
+ for (const [projectId, teamId, projectName, teamName] of [
118
+ [
119
+ firstProjectId,
120
+ firstTeamId,
121
+ "First invitation project",
122
+ "First invitation team",
123
+ ],
124
+ [
125
+ secondProjectId,
126
+ secondTeamId,
127
+ "Second invitation project",
128
+ "Second invitation team",
129
+ ],
130
+ ] as Array<[ObjectID, ObjectID, string, string]>) {
131
+ await database.query(
132
+ `INSERT INTO "${schema}"."Project" ("_id", "name", "slug", "version") VALUES ($1, $2, $3, 1)`,
133
+ [projectId.toString(), projectName, projectId.toString()],
134
+ );
135
+ await database.query(
136
+ `INSERT INTO "${schema}"."Team" ("_id", "projectId", "name", "slug", "description", "version")
137
+ VALUES ($1, $2, $3, $4, $5, 1)`,
138
+ [
139
+ teamId.toString(),
140
+ projectId.toString(),
141
+ teamName,
142
+ teamId.toString(),
143
+ privateTeamDescription,
144
+ ],
145
+ );
146
+ }
147
+ for (const [id, memberId, projectId, teamId, accepted] of [
148
+ [firstInvitationId, userId, firstProjectId, firstTeamId, false],
149
+ [secondInvitationId, userId, secondProjectId, secondTeamId, false],
150
+ [otherInvitationId, otherUserId, firstProjectId, firstTeamId, false],
151
+ [acceptedMembershipId, userId, firstProjectId, firstTeamId, true],
152
+ ] as Array<[ObjectID, ObjectID, ObjectID, ObjectID, boolean]>) {
153
+ await database.query(
154
+ `INSERT INTO "${schema}"."TeamMember"
155
+ ("_id", "userId", "projectId", "teamId", "createdByUserId", "hasAcceptedInvitation", "version")
156
+ VALUES ($1, $2, $3, $4, $5, $6, 1)`,
157
+ [
158
+ id.toString(),
159
+ memberId.toString(),
160
+ projectId.toString(),
161
+ teamId.toString(),
162
+ inviterId.toString(),
163
+ accepted,
164
+ ],
165
+ );
166
+ }
167
+ });
168
+
169
+ afterAll(async () => {
170
+ jest.restoreAllMocks();
171
+ if (database?.isInitialized) {
172
+ await database.query(`DROP SCHEMA IF EXISTS "${schema}" CASCADE`);
173
+ await database.destroy();
174
+ }
175
+ });
176
+
177
+ function props(
178
+ isMultiTenantRequest: boolean = true,
179
+ ): DatabaseCommonInteractionProps {
180
+ return {
181
+ userId,
182
+ userType: UserType.User,
183
+ isMultiTenantRequest,
184
+ userGlobalAccessPermission: {
185
+ _type: "UserGlobalAccessPermission",
186
+ globalPermissions: [Permission.User, Permission.CurrentUser],
187
+ // An invited user may not belong to any project yet.
188
+ projectIds: [],
189
+ },
190
+ };
191
+ }
192
+
193
+ function safeSelect(): Select<TeamMember> {
194
+ return {
195
+ _id: true,
196
+ userId: true,
197
+ hasAcceptedInvitation: true,
198
+ team: { name: true },
199
+ project: { name: true },
200
+ };
201
+ }
202
+
203
+ async function getList(data: {
204
+ select: Select<TeamMember>;
205
+ query?: JSONObject;
206
+ isMultiTenantRequest?: boolean;
207
+ }): Promise<JSONObject> {
208
+ const requestProps: DatabaseCommonInteractionProps = props();
209
+ const req: OneUptimeRequest = {
210
+ headers:
211
+ data.isMultiTenantRequest === false
212
+ ? {}
213
+ : { "is-multi-tenant-query": "true" },
214
+ query: {},
215
+ body: JSONFunctions.serialize({
216
+ query: data.query || {},
217
+ select: data.select,
218
+ limit: 20,
219
+ }),
220
+ userAuthorization: { userId },
221
+ userGlobalAccessPermission: requestProps.userGlobalAccessPermission,
222
+ userType: UserType.User,
223
+ } as unknown as OneUptimeRequest;
224
+ let body: JSONObject | undefined;
225
+ const res: ExpressResponse = {
226
+ status: jest.fn().mockReturnThis(),
227
+ set: jest.fn().mockReturnThis(),
228
+ send: jest.fn((responseBody: JSONObject) => {
229
+ // Express serializes ListData and its database property wrappers.
230
+ body = JSON.parse(JSON.stringify(responseBody)) as JSONObject;
231
+ }),
232
+ } as unknown as ExpressResponse;
233
+ await api.getList(req, res);
234
+ expect(res.status).toHaveBeenCalledWith(200);
235
+ expect(body).toBeDefined();
236
+ return body as JSONObject;
237
+ }
238
+
239
+ test("the privileged control reaches synthetic inviter secrets through the real join and serializer", async () => {
240
+ const records: Array<TeamMember> = await service.findBy({
241
+ query: { _id: firstInvitationId.toString() },
242
+ select: { createdByUser: { password: true, resetPasswordToken: true } },
243
+ skip: 0,
244
+ limit: 1,
245
+ props: { isRoot: true },
246
+ });
247
+ expect(records).toHaveLength(1);
248
+ const serialized: string = JSON.stringify(
249
+ BaseModel.toJSONArray(records, TeamMember),
250
+ );
251
+ expect(serialized).toContain(passwordHash);
252
+ expect(serialized).toContain(resetToken);
253
+ });
254
+
255
+ test.each([
256
+ [
257
+ "inviter password hash",
258
+ { createdByUser: { password: true } },
259
+ "permissions to select on - createdByUser",
260
+ ],
261
+ [
262
+ "inviter password reset token",
263
+ { createdByUser: { resetPasswordToken: true } },
264
+ "permissions to select on - createdByUser",
265
+ ],
266
+ [
267
+ "restricted team field",
268
+ { team: { description: true } },
269
+ "Column description on Team does not support read on relation query",
270
+ ],
271
+ [
272
+ "restricted user relation",
273
+ { user: { password: true } },
274
+ "permissions to select on - user",
275
+ ],
276
+ [
277
+ "deep relation",
278
+ { team: { createdByUser: { password: true } } },
279
+ "You cannot query deep relations",
280
+ ],
281
+ ] as Array<[string, Select<TeamMember>, string]>)(
282
+ "rejects a multi-tenant API selection of %s",
283
+ async (
284
+ _label: string,
285
+ select: Select<TeamMember>,
286
+ expectedError: string,
287
+ ) => {
288
+ await expect(getList({ select })).rejects.toThrow(expectedError);
289
+ },
290
+ );
291
+
292
+ test("the same nested credential projection is already denied without the multi-tenant header", async () => {
293
+ await expect(
294
+ getList({
295
+ select: {
296
+ createdByUser: { password: true, resetPasswordToken: true },
297
+ },
298
+ isMultiTenantRequest: false,
299
+ }),
300
+ ).rejects.toThrow("permissions to select on - createdByUser");
301
+ });
302
+
303
+ test.each([true, false])(
304
+ "lists pending invitations and their safe labels with no project memberships (multi-tenant=%s)",
305
+ async (isMultiTenantRequest: boolean) => {
306
+ const response: JSONObject = await getList({
307
+ select: safeSelect(),
308
+ query: { hasAcceptedInvitation: false },
309
+ isMultiTenantRequest,
310
+ });
311
+ expect(response["count"]).toBe(2);
312
+ const rows: Array<JSONObject> = response["data"] as Array<JSONObject>;
313
+ expect(rows).toHaveLength(2);
314
+ expect(
315
+ rows
316
+ .map((row: JSONObject) => {
317
+ return row["_id"];
318
+ })
319
+ .sort(),
320
+ ).toEqual(
321
+ [firstInvitationId.toString(), secondInvitationId.toString()].sort(),
322
+ );
323
+ const serialized: string = JSON.stringify(response);
324
+ expect(serialized).toContain("First invitation project");
325
+ expect(serialized).toContain("Second invitation project");
326
+ expect(serialized).toContain("First invitation team");
327
+ expect(serialized).toContain("Second invitation team");
328
+ expect(serialized).not.toContain(otherInvitationId.toString());
329
+ expect(serialized).not.toContain(passwordHash);
330
+ expect(serialized).not.toContain(resetToken);
331
+ expect(serialized).not.toContain(privateTeamDescription);
332
+ },
333
+ );
334
+
335
+ test("caller filters remain effective for both list and count", async () => {
336
+ const response: JSONObject = await getList({
337
+ select: safeSelect(),
338
+ query: { projectId: secondProjectId, hasAcceptedInvitation: false },
339
+ });
340
+ expect(response["count"]).toBe(1);
341
+ expect(response["data"]).toHaveLength(1);
342
+ expect(JSON.stringify(response)).toContain(secondInvitationId.toString());
343
+ expect(JSON.stringify(response)).not.toContain(
344
+ firstInvitationId.toString(),
345
+ );
346
+ });
347
+
348
+ test("count authorization rejects predicates on forbidden columns", async () => {
349
+ await expect(
350
+ service.countBy({
351
+ query: { createdByUserId: inviterId },
352
+ props: props(),
353
+ }),
354
+ ).rejects.toThrow("permissions to query on - createdByUserId");
355
+ });
356
+
357
+ test("safe counts are restricted to the current user's rows", async () => {
358
+ expect(
359
+ (await service.countBy({ query: {}, props: props() })).toNumber(),
360
+ ).toBe(3);
361
+ expect(
362
+ (
363
+ await service.countBy({
364
+ query: { hasAcceptedInvitation: false },
365
+ props: props(),
366
+ })
367
+ ).toNumber(),
368
+ ).toBe(2);
369
+ expect(
370
+ (
371
+ await service.countBy({ query: {}, props: { isRoot: true } })
372
+ ).toNumber(),
373
+ ).toBe(4);
374
+ });
375
+
376
+ test("a caller cannot redirect the current-user scope to another member", async () => {
377
+ await expect(
378
+ getList({ select: safeSelect(), query: { userId: otherUserId } }),
379
+ ).rejects.toThrow("permission to access another user's Team Member");
380
+ await expect(
381
+ service.countBy({ query: { userId: otherUserId }, props: props() }),
382
+ ).rejects.toThrow("permission to access another user's Team Member");
383
+ });
384
+
385
+ test("an explicit foreign membership ID returns no row and a zero count", async () => {
386
+ const response: JSONObject = await getList({
387
+ select: safeSelect(),
388
+ query: { _id: otherInvitationId.toString() },
389
+ });
390
+ expect(response["data"]).toEqual([]);
391
+ expect(response["count"]).toBe(0);
392
+ });
393
+ },
394
+ );
@@ -103,6 +103,11 @@ function propsWith(
103
103
  return {
104
104
  userId: USER_ID,
105
105
  tenantId: tenantId,
106
+ userGlobalAccessPermission: {
107
+ _type: "UserGlobalAccessPermission",
108
+ projectIds: [tenantId],
109
+ globalPermissions: [Permission.Public, Permission.User],
110
+ },
106
111
  userTenantAccessPermission: {
107
112
  [tenantId.toString()]: tenantPermission,
108
113
  },
@@ -117,6 +122,7 @@ function makePermission(data?: {
117
122
  scope?: PermissionScope | undefined;
118
123
  }): TeamPermission {
119
124
  const permission: TeamPermission = new TeamPermission();
125
+ permission.id = ObjectID.generate();
120
126
  permission.projectId = data?.projectId || PROJECT_ID;
121
127
  permission.teamId = data?.teamId || TEAM_ID;
122
128
  permission.permission = data?.permission || Permission.ProjectMember;
@@ -2,10 +2,13 @@ import TelemetryIngestionKeyService, {
2
2
  Service,
3
3
  } from "../../../Server/Services/TelemetryIngestionKeyService";
4
4
  import PayAsYouGoBillingService from "../../../Server/Services/PayAsYouGoBillingService";
5
+ import BillingService from "../../../Server/Services/BillingService";
6
+ import ProjectService from "../../../Server/Services/ProjectService";
5
7
  import TelemetryIngest, {
6
8
  TelemetryRequest,
7
9
  } from "../../../Server/Middleware/TelemetryIngest";
8
10
  import TelemetryIngestionKey from "../../../Models/DatabaseModels/TelemetryIngestionKey";
11
+ import Project from "../../../Models/DatabaseModels/Project";
9
12
  import CreateBy from "../../../Server/Types/Database/CreateBy";
10
13
  import UpdateBy from "../../../Server/Types/Database/UpdateBy";
11
14
  import {
@@ -16,6 +19,9 @@ import {
16
19
  import TelemetryIngestSurface from "../../../Types/Telemetry/TelemetryIngestSurface";
17
20
  import TelemetryIngestionKeyType from "../../../Types/Telemetry/TelemetryIngestionKeyType";
18
21
  import PaymentRequiredException from "../../../Types/Exception/PaymentRequiredException";
22
+ import SubscriptionPlan, {
23
+ PlanType,
24
+ } from "../../../Types/Billing/SubscriptionPlan";
19
25
  import ObjectID from "../../../Types/ObjectID";
20
26
  import * as EnvironmentConfig from "../../../Server/EnvironmentConfig";
21
27
  import {
@@ -101,6 +107,25 @@ function expectPaymentCheckedFor(project: ObjectID): void {
101
107
  }
102
108
  }
103
109
 
110
+ function useRealPaymentEligibility(plan: PlanType): void {
111
+ jest.mocked(PayAsYouGoBillingService.canUsePayAsYouGo).mockRestore();
112
+ PayAsYouGoBillingService.invalidate(projectId);
113
+ PayAsYouGoBillingService.invalidate(otherProjectId);
114
+ jest.spyOn(BillingService, "isBillingEnabled").mockReturnValue(true);
115
+ jest.spyOn(BillingService, "hasPaymentMethods").mockResolvedValue(false);
116
+ jest.spyOn(ProjectService, "findOneById").mockResolvedValue(
117
+ Object.assign(new Project(), {
118
+ paymentProviderPlanId: plan,
119
+ paymentProviderCustomerId: "cus_telemetry_project",
120
+ }),
121
+ );
122
+ jest
123
+ .spyOn(SubscriptionPlan, "getSubscriptionPlanById")
124
+ .mockReturnValue(
125
+ new SubscriptionPlan(plan, `${plan}_yearly`, plan, 0, 0, 0, 0),
126
+ );
127
+ }
128
+
104
129
  beforeEach(() => {
105
130
  jest.restoreAllMocks();
106
131
  (EnvironmentConfig as { IsBillingEnabled: boolean }).IsBillingEnabled = true;
@@ -353,3 +378,109 @@ describe("HTTP telemetry admission integrates key resolution and billing", () =>
353
378
  expect(TelemetryIngestionKeyService.markUsed).toHaveBeenCalledTimes(1);
354
379
  });
355
380
  });
381
+
382
+ describe("telemetry operations use the stored subscription plan for payment eligibility", () => {
383
+ describe.each([PlanType.Growth, PlanType.Scale, PlanType.Enterprise])(
384
+ "%s telemetry keys without a payment method",
385
+ (plan: PlanType) => {
386
+ test.each(Object.values(TelemetryIngestionKeyType))(
387
+ "allows creating a %s key",
388
+ async (keyType: TelemetryIngestionKeyType) => {
389
+ useRealPaymentEligibility(plan);
390
+ const input: CreateBy<TelemetryIngestionKey> = createInput();
391
+ input.data.keyType = keyType;
392
+ input.data.allowedOrigins = ["https://example.com"];
393
+
394
+ await expect(hooks.onBeforeCreate(input)).resolves.toBeDefined();
395
+
396
+ expect(ProjectService.findOneById).toHaveBeenCalledWith(
397
+ expect.objectContaining({ id: projectId }),
398
+ );
399
+ expect(BillingService.hasPaymentMethods).not.toHaveBeenCalled();
400
+ },
401
+ );
402
+
403
+ test("allows re-enabling a key using its stored project", async () => {
404
+ useRealPaymentEligibility(plan);
405
+ jest.spyOn(service, "findBy").mockResolvedValue([key(otherProjectId)]);
406
+
407
+ await expect(
408
+ hooks.onBeforeUpdate(updateInput({ isEnabled: true })),
409
+ ).resolves.toBeDefined();
410
+
411
+ expect(ProjectService.findOneById).toHaveBeenCalledWith(
412
+ expect.objectContaining({ id: otherProjectId }),
413
+ );
414
+ expect(BillingService.hasPaymentMethods).not.toHaveBeenCalled();
415
+ });
416
+ },
417
+ );
418
+
419
+ test("still requires a payment method to create or re-enable Free telemetry keys", async () => {
420
+ useRealPaymentEligibility(PlanType.Free);
421
+ jest.spyOn(service, "findBy").mockResolvedValue([key()]);
422
+
423
+ await expect(hooks.onBeforeCreate(createInput())).rejects.toBeInstanceOf(
424
+ PaymentRequiredException,
425
+ );
426
+ await expect(
427
+ hooks.onBeforeUpdate(updateInput({ isEnabled: true })),
428
+ ).rejects.toBeInstanceOf(PaymentRequiredException);
429
+
430
+ expect(BillingService.hasPaymentMethods).toHaveBeenCalledWith(
431
+ "cus_telemetry_project",
432
+ );
433
+ });
434
+
435
+ describe.each([
436
+ PlanType.Free,
437
+ PlanType.Growth,
438
+ PlanType.Scale,
439
+ PlanType.Enterprise,
440
+ ])("%s HTTP telemetry without a payment method", (plan: PlanType) => {
441
+ test.each(Object.values(TelemetryIngestSurface))(
442
+ "applies plan eligibility before the %s handler",
443
+ async (surface: TelemetryIngestSurface) => {
444
+ useRealPaymentEligibility(plan);
445
+ const existingKey: TelemetryIngestionKey = key();
446
+ jest
447
+ .spyOn(TelemetryIngestionKeyService, "findOneBy")
448
+ .mockResolvedValue(existingKey);
449
+ jest
450
+ .spyOn(TelemetryIngestionKeyService, "markUsed")
451
+ .mockResolvedValue(undefined);
452
+ const request: ExpressRequest = {
453
+ headers: { "x-oneuptime-token": existingKey.secretKey!.toString() },
454
+ } as unknown as ExpressRequest;
455
+ const next: NextFunction = jest.fn() as unknown as NextFunction;
456
+
457
+ await TelemetryIngest.forSurface(surface)(
458
+ request,
459
+ {} as ExpressResponse,
460
+ next,
461
+ );
462
+
463
+ expect(next).toHaveBeenCalledTimes(1);
464
+ if (plan === PlanType.Free) {
465
+ expect(next).toHaveBeenCalledWith(
466
+ expect.any(PaymentRequiredException),
467
+ );
468
+ expect((request as TelemetryRequest).projectId).toBeUndefined();
469
+ expect(TelemetryIngestionKeyService.markUsed).not.toHaveBeenCalled();
470
+ expect(BillingService.hasPaymentMethods).toHaveBeenCalledWith(
471
+ "cus_telemetry_project",
472
+ );
473
+ } else {
474
+ expect(next).toHaveBeenCalledWith();
475
+ expect((request as TelemetryRequest).projectId.toString()).toBe(
476
+ projectId.toString(),
477
+ );
478
+ expect(TelemetryIngestionKeyService.markUsed).toHaveBeenCalledTimes(
479
+ 1,
480
+ );
481
+ expect(BillingService.hasPaymentMethods).not.toHaveBeenCalled();
482
+ }
483
+ },
484
+ );
485
+ });
486
+ });
@@ -38,6 +38,7 @@ import NotificationRuleType from "../../../Types/NotificationRule/NotificationRu
38
38
  import ObjectID from "../../../Types/ObjectID";
39
39
  import UserNotificationEventType from "../../../Types/UserNotification/UserNotificationEventType";
40
40
  import UserNotificationStatus from "../../../Types/UserNotification/UserNotificationStatus";
41
+ import UserType from "../../../Types/UserType";
41
42
  import { afterEach, beforeEach, describe, expect, test } from "@jest/globals";
42
43
 
43
44
  /*
@@ -616,6 +617,11 @@ describe("UserNotificationRule administrative write guards", () => {
616
617
  * An API key has no user identity. If the widened create list ever admits
617
618
  * one, "actor equals owner" is trivially false and must NOT be read as
618
619
  * "nobody else involved, carry on".
620
+ *
621
+ * The fixture says userType API because an API key is the only actor-less
622
+ * caller that can reach this hook: DatabaseService.create now refuses a
623
+ * caller with no credentials at all (no userId, not an API key) with a
624
+ * 401 before any hook runs.
619
625
  */
620
626
  stubs.teamMemberFind.mockResolvedValue(null as never);
621
627
 
@@ -623,7 +629,7 @@ describe("UserNotificationRule administrative write guards", () => {
623
629
  hooks().onBeforeCreate(
624
630
  createBy({
625
631
  userId: VICTIM_USER_ID,
626
- props: { tenantId: PROJECT_ID },
632
+ props: { tenantId: PROJECT_ID, userType: UserType.API },
627
633
  channels: { userEmailId: METHOD_ID },
628
634
  }),
629
635
  ),
@@ -631,10 +637,15 @@ describe("UserNotificationRule administrative write guards", () => {
631
637
  });
632
638
 
633
639
  test("a rule with neither an owner nor an actor is refused rather than written unowned", async () => {
640
+ /*
641
+ * Actor-less means an API key here, for the same reason as above: an
642
+ * anonymous caller is refused (401) by DatabaseService.create before
643
+ * this hook, so it never sees this 400.
644
+ */
634
645
  await expect(
635
646
  hooks().onBeforeCreate(
636
647
  createBy({
637
- props: { tenantId: PROJECT_ID },
648
+ props: { tenantId: PROJECT_ID, userType: UserType.API },
638
649
  channels: { userEmailId: METHOD_ID },
639
650
  }),
640
651
  ),