@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,12 @@
1
+ /*
2
+ * The browser client builds IDENTITY_URL (where the session is refreshed) and
3
+ * the other service URLs from HOST once, when UI/Config is first loaded. With
4
+ * no HOST the refresh URL degenerates to "http://identity/refresh-token", which
5
+ * is not a URL any browser would call. Importing this module FIRST gives the
6
+ * client the host a real Dashboard runs on. Jest gives each test file its own
7
+ * copy of process.env, so this does not leak into other files.
8
+ */
9
+ export const DASHBOARD_ORIGIN: string = "https://oneuptime.example.com";
10
+
11
+ process.env["HOST"] = "oneuptime.example.com";
12
+ process.env["HTTP_PROTOCOL"] = "https";
@@ -0,0 +1,183 @@
1
+ import HTTPMethod from "../../../../Types/API/HTTPMethod";
2
+ import Dictionary from "../../../../Types/Dictionary";
3
+ import { JSONArray, JSONObject } from "../../../../Types/JSON";
4
+ import {
5
+ AxiosError,
6
+ AxiosHeaders,
7
+ AxiosRequestConfig,
8
+ AxiosResponse,
9
+ InternalAxiosRequestConfig,
10
+ } from "axios";
11
+
12
+ /*
13
+ * A scripted stand-in for the server, sitting where axios's transport would.
14
+ *
15
+ * Common/Utils/API.ts calls `axios(config)` and relies on axios for the one
16
+ * behaviour everything in these tests hangs on: a 4xx/5xx REJECTS with an
17
+ * AxiosError carrying `response.status`, and a request that never got an answer
18
+ * rejects with no `response` at all. The fake reproduces exactly that, with real
19
+ * AxiosError instances, so `axios.isAxiosError` and the 401 branch in
20
+ * fetchUntraced see what they would see in a browser.
21
+ *
22
+ * Every route is scripted with the replies it gives, in order. A request the
23
+ * script did not expect - an extra refresh, a replay that should not have
24
+ * happened - is answered with a plain Error, which the client turns into a
25
+ * thrown APIException that fails the test naming the unexpected request.
26
+ */
27
+
28
+ export type FakeTransport = jest.MockedFunction<
29
+ (config: AxiosRequestConfig) => Promise<AxiosResponse>
30
+ >;
31
+
32
+ export interface FakeReply {
33
+ // HTTP status to answer with. 2xx resolves; anything else rejects, as axios does.
34
+ status?: number | undefined;
35
+ data?: JSONObject | JSONArray | undefined;
36
+ headers?: Dictionary<string> | undefined;
37
+ // Fail without any response, the way a refused or dropped connection does.
38
+ networkErrorCode?: string | undefined;
39
+ // Hold the reply until this settles, to keep a request in flight on purpose.
40
+ gate?: Promise<void> | undefined;
41
+ }
42
+
43
+ export interface SentRequest {
44
+ method: string;
45
+ url: string;
46
+ data: unknown;
47
+ headers: Dictionary<string>;
48
+ }
49
+
50
+ export interface Gate {
51
+ promise: Promise<void>;
52
+ open: () => void;
53
+ }
54
+
55
+ export const createGate: () => Gate = (): Gate => {
56
+ let open: () => void = (): void => {};
57
+
58
+ const promise: Promise<void> = new Promise<void>((resolve: () => void) => {
59
+ open = resolve;
60
+ });
61
+
62
+ return { promise: promise, open: open };
63
+ };
64
+
65
+ /*
66
+ * Lets every promise chain that is already runnable finish. A macrotask runs
67
+ * only once the microtask queue is empty, so after this every request that
68
+ * could reach the fake without outside help has done so.
69
+ */
70
+ export const settle: () => Promise<void> = async (): Promise<void> => {
71
+ await new Promise<void>((resolve: () => void) => {
72
+ setTimeout(resolve, 0);
73
+ });
74
+ };
75
+
76
+ export default class FakeAxiosServer {
77
+ public readonly sent: Array<SentRequest> = [];
78
+
79
+ // Called for every request as it arrives, before it is answered.
80
+ public onRequest: ((request: SentRequest) => void) | null = null;
81
+
82
+ private readonly routes: Map<string, Array<FakeReply>> = new Map();
83
+
84
+ private readonly transport: FakeTransport;
85
+
86
+ public constructor(transport: FakeTransport) {
87
+ this.transport = transport;
88
+
89
+ this.transport.mockImplementation(
90
+ async (config: AxiosRequestConfig): Promise<AxiosResponse> => {
91
+ return await this.handle(config);
92
+ },
93
+ );
94
+ }
95
+
96
+ public on(method: HTTPMethod, url: string, replies: Array<FakeReply>): this {
97
+ const key: string = FakeAxiosServer.key(method, url);
98
+
99
+ this.routes.set(key, [...(this.routes.get(key) || []), ...replies]);
100
+
101
+ return this;
102
+ }
103
+
104
+ public requestsTo(method: HTTPMethod, url: string): Array<SentRequest> {
105
+ return this.sent.filter((request: SentRequest): boolean => {
106
+ return (
107
+ request.method.toUpperCase() === method.toUpperCase() &&
108
+ request.url === url
109
+ );
110
+ });
111
+ }
112
+
113
+ private static key(method: string, url: string): string {
114
+ return `${method.toUpperCase()} ${url}`;
115
+ }
116
+
117
+ private async handle(config: AxiosRequestConfig): Promise<AxiosResponse> {
118
+ const request: SentRequest = {
119
+ method: String(config.method || ""),
120
+ url: String(config.url || ""),
121
+ data: config.data,
122
+ headers: { ...((config.headers || {}) as Dictionary<string>) },
123
+ };
124
+
125
+ this.sent.push(request);
126
+
127
+ if (this.onRequest) {
128
+ this.onRequest(request);
129
+ }
130
+
131
+ const queue: Array<FakeReply> | undefined = this.routes.get(
132
+ FakeAxiosServer.key(request.method, request.url),
133
+ );
134
+
135
+ const reply: FakeReply | undefined = queue ? queue.shift() : undefined;
136
+
137
+ if (!reply) {
138
+ throw new Error(
139
+ `Unexpected request: ${request.method.toUpperCase()} ${request.url}`,
140
+ );
141
+ }
142
+
143
+ if (reply.gate) {
144
+ await reply.gate;
145
+ }
146
+
147
+ const internalConfig: InternalAxiosRequestConfig = {
148
+ ...config,
149
+ headers: new AxiosHeaders(),
150
+ } as InternalAxiosRequestConfig;
151
+
152
+ if (reply.networkErrorCode) {
153
+ throw new AxiosError(
154
+ `connect ${reply.networkErrorCode}`,
155
+ reply.networkErrorCode,
156
+ internalConfig,
157
+ {},
158
+ );
159
+ }
160
+
161
+ const status: number = reply.status ?? 200;
162
+
163
+ const response: AxiosResponse = {
164
+ data: reply.data ?? {},
165
+ status: status,
166
+ statusText: "",
167
+ headers: reply.headers ?? {},
168
+ config: internalConfig,
169
+ };
170
+
171
+ if (status >= 200 && status < 300) {
172
+ return response;
173
+ }
174
+
175
+ throw new AxiosError(
176
+ `Request failed with status code ${status}`,
177
+ status >= 500 ? "ERR_BAD_RESPONSE" : "ERR_BAD_REQUEST",
178
+ internalConfig,
179
+ {},
180
+ response,
181
+ );
182
+ }
183
+ }
@@ -1538,6 +1538,11 @@ const realBreadcrumbTrails: Array<BreadcrumbTrailFixture> = [
1538
1538
  pagePattern: "/dashboard/:projectId/on-call-duty/calendar-feeds",
1539
1539
  titles: ["Project", "On-Call Duty", "Calendar Feeds"],
1540
1540
  },
1541
+ {
1542
+ getter: "getOnCallDutyBreadcrumbs",
1543
+ pagePattern: "/dashboard/:projectId/on-call-duty/schedule-timeline",
1544
+ titles: ["Project", "On-Call Duty", "Schedule Timeline"],
1545
+ },
1541
1546
  {
1542
1547
  getter: "getOnCallDutyBreadcrumbs",
1543
1548
  pagePattern: "/dashboard/:projectId/on-call-duty/execution-logs",
@@ -2778,6 +2783,11 @@ const realBreadcrumbTrails: Array<BreadcrumbTrailFixture> = [
2778
2783
  pagePattern: "/dashboard/:projectId/teams/:id/compliance",
2779
2784
  titles: ["Project", "Teams", "View Team", "Compliance"],
2780
2785
  },
2786
+ {
2787
+ getter: "getTeamsBreadcrumbs",
2788
+ pagePattern: "/dashboard/:projectId/teams/:id/on-call-schedules",
2789
+ titles: ["Project", "Teams", "View Team", "On-Call Schedules"],
2790
+ },
2781
2791
  {
2782
2792
  getter: "getTeamsBreadcrumbs",
2783
2793
  pagePattern: "/dashboard/:projectId/teams/:id/custom-fields",
@@ -580,6 +580,7 @@ const realRoutePatterns: Array<string> = [
580
580
  "/dashboard/:projectId/on-call-duty/*",
581
581
  "/dashboard/:projectId/on-call-duty/policies",
582
582
  "/dashboard/:projectId/on-call-duty/calendar-feeds",
583
+ "/dashboard/:projectId/on-call-duty/schedule-timeline",
583
584
  "/dashboard/:projectId/on-call-duty/schedules",
584
585
  "/dashboard/:projectId/on-call-duty/schedules/:id",
585
586
  "/dashboard/:projectId/on-call-duty/schedules/:id/delete",
@@ -684,6 +685,7 @@ const realRoutePatterns: Array<string> = [
684
685
  "/dashboard/:projectId/teams/:id/permissions",
685
686
  "/dashboard/:projectId/teams/:id/block-permissions",
686
687
  "/dashboard/:projectId/teams/:id/compliance",
688
+ "/dashboard/:projectId/teams/:id/on-call-schedules",
687
689
  "/dashboard/:projectId/teams/:id/custom-fields",
688
690
  "/dashboard/:projectId/teams/:id/delete",
689
691
  "/dashboard/:projectId/settings/*",
@@ -0,0 +1,440 @@
1
+ import { afterEach, beforeEach, describe, expect, it } from "@jest/globals";
2
+ import Cookie from "../../../UI/Utils/Cookie";
3
+ import CookieName from "../../../Types/CookieName";
4
+ import Route from "../../../Types/API/Route";
5
+ import Email from "../../../Types/Email";
6
+ import URL from "../../../Types/API/URL";
7
+ import { JSONObject, JSONValue } from "../../../Types/JSON";
8
+
9
+ /*
10
+ * Cookie is a thin wrapper around universal-cookie, which in jsdom writes
11
+ * straight through to `document.cookie`. Rather than mocking the library, these
12
+ * tests observe the real cookie jar and, where the exact attributes matter
13
+ * (Path, Max-Age, HttpOnly), record every raw string assigned to
14
+ * `document.cookie` so the serialized header can be asserted.
15
+ */
16
+
17
+ const cookieDescriptor: PropertyDescriptor = Object.getOwnPropertyDescriptor(
18
+ Document.prototype,
19
+ "cookie",
20
+ ) as PropertyDescriptor;
21
+
22
+ let cookieWrites: Array<string> = [];
23
+
24
+ const installCookieWriteRecorder: () => void = (): void => {
25
+ Object.defineProperty(document, "cookie", {
26
+ configurable: true,
27
+ get: (): string => {
28
+ return cookieDescriptor.get!.call(document) as string;
29
+ },
30
+ set: (value: string): void => {
31
+ cookieWrites.push(value);
32
+ cookieDescriptor.set!.call(document, value);
33
+ },
34
+ });
35
+ };
36
+
37
+ const uninstallCookieWriteRecorder: () => void = (): void => {
38
+ // Remove the own-property override so the prototype accessor is used again.
39
+ delete (document as unknown as { cookie?: string }).cookie;
40
+ };
41
+
42
+ const readRawJar: () => { [key: string]: string } = (): {
43
+ [key: string]: string;
44
+ } => {
45
+ const jar: { [key: string]: string } = {};
46
+ const raw: string = document.cookie;
47
+
48
+ if (!raw) {
49
+ return jar;
50
+ }
51
+
52
+ for (const part of raw.split(";")) {
53
+ const index: number = part.indexOf("=");
54
+ const name: string = part.slice(0, index).trim();
55
+ const value: string = part.slice(index + 1).trim();
56
+ jar[name] = decodeURIComponent(value);
57
+ }
58
+
59
+ return jar;
60
+ };
61
+
62
+ const expireEverything: () => void = (): void => {
63
+ const paths: Array<string> = ["/", "/dashboard", "/dashboard/project"];
64
+
65
+ for (const name of Object.keys(readRawJar())) {
66
+ for (const path of paths) {
67
+ document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 GMT; path=${path}`;
68
+ }
69
+ }
70
+ };
71
+
72
+ const lastWriteFor: (name: string) => string = (name: string): string => {
73
+ const writes: Array<string> = cookieWrites.filter((write: string) => {
74
+ return write.startsWith(`${name}=`);
75
+ });
76
+
77
+ expect(writes.length).toBeGreaterThan(0);
78
+ return writes[writes.length - 1] as string;
79
+ };
80
+
81
+ describe("UI Cookie util", () => {
82
+ beforeEach(() => {
83
+ window.history.replaceState({}, "", "/");
84
+ expireEverything();
85
+ cookieWrites = [];
86
+ installCookieWriteRecorder();
87
+ });
88
+
89
+ afterEach(() => {
90
+ uninstallCookieWriteRecorder();
91
+ window.history.replaceState({}, "", "/");
92
+ expireEverything();
93
+ });
94
+
95
+ describe("setItem", () => {
96
+ it("stores a plain string value unchanged at the root path by default", () => {
97
+ Cookie.setItem(CookieName.UserID, "user-123");
98
+
99
+ expect(readRawJar()[CookieName.UserID]).toBe("user-123");
100
+
101
+ const write: string = lastWriteFor(CookieName.UserID);
102
+ expect(write).toContain("Path=/");
103
+ expect(write).not.toContain("HttpOnly");
104
+ expect(write).not.toContain("Max-Age");
105
+ });
106
+
107
+ it("URL-encodes characters that are not legal in a cookie value", () => {
108
+ const value: string = "Jane Doe; admin=true, héllo";
109
+
110
+ Cookie.setItem(CookieName.Name, value);
111
+
112
+ const write: string = lastWriteFor(CookieName.Name);
113
+ /*
114
+ * The raw header must not contain the separator characters verbatim,
115
+ * otherwise "; admin=true" would be read as a cookie attribute.
116
+ */
117
+ expect(write.split(";")[0]).not.toContain(" ");
118
+ expect(write.split(";")[0]).not.toContain(",");
119
+ expect(write).not.toContain("admin=true");
120
+
121
+ expect(readRawJar()[CookieName.Name]).toBe(value);
122
+ expect(Cookie.getItem(CookieName.Name)).toBe(value);
123
+ });
124
+
125
+ it("uses the supplied Route as the cookie path", () => {
126
+ Cookie.setItem(CookieName.Timezone, "UTC", {
127
+ path: new Route("/dashboard"),
128
+ });
129
+
130
+ expect(lastWriteFor(CookieName.Timezone)).toContain("Path=/dashboard");
131
+
132
+ // A cookie scoped to /dashboard is not visible from the root.
133
+ expect(readRawJar()[CookieName.Timezone]).toBeUndefined();
134
+
135
+ window.history.replaceState({}, "", "/dashboard/home");
136
+ expect(readRawJar()[CookieName.Timezone]).toBe("UTC");
137
+ });
138
+
139
+ it("does not set Max-Age when maxAgeInDays is omitted or zero", () => {
140
+ Cookie.setItem(CookieName.UserID, "a", {
141
+ path: new Route("/"),
142
+ });
143
+ expect(lastWriteFor(CookieName.UserID)).not.toContain("Max-Age");
144
+
145
+ Cookie.setItem(CookieName.UserID, "b", {
146
+ path: new Route("/"),
147
+ maxAgeInDays: 0,
148
+ });
149
+ expect(lastWriteFor(CookieName.UserID)).not.toContain("Max-Age");
150
+ expect(readRawJar()[CookieName.UserID]).toBe("b");
151
+ });
152
+
153
+ it("sets a Max-Age attribute when maxAgeInDays is provided", () => {
154
+ Cookie.setItem(CookieName.UserID, "persistent", {
155
+ path: new Route("/"),
156
+ maxAgeInDays: 30,
157
+ });
158
+
159
+ const write: string = lastWriteFor(CookieName.UserID);
160
+ const match: RegExpMatchArray | null = write.match(/Max-Age=(\d+)/);
161
+
162
+ expect(match).not.toBeNull();
163
+ // At minimum the cookie must live for the requested 30 days.
164
+ expect(Number(match![1])).toBeGreaterThanOrEqual(30 * 24 * 60 * 60);
165
+ expect(readRawJar()[CookieName.UserID]).toBe("persistent");
166
+ });
167
+
168
+ /*
169
+ * universal-cookie (and the Set-Cookie spec) interpret maxAge in SECONDS,
170
+ * but Cookie.setItem passes OneUptimeDate.getMillisecondsInDays(), so a
171
+ * 1-day cookie is written with Max-Age=86400000 (~1000 days). This test
172
+ * documents the expected behaviour and is marked `failing` until the
173
+ * source is fixed; when it starts passing, drop the `.failing`.
174
+ */
175
+ it.failing(
176
+ "writes Max-Age in seconds (1 day => 86400) [known bug: uses milliseconds]",
177
+ () => {
178
+ Cookie.setItem(CookieName.UserID, "one-day", {
179
+ path: new Route("/"),
180
+ maxAgeInDays: 1,
181
+ });
182
+
183
+ expect(lastWriteFor(CookieName.UserID)).toContain("Max-Age=86400;");
184
+ },
185
+ );
186
+
187
+ it("currently writes Max-Age in milliseconds (1 day => 86400000)", () => {
188
+ Cookie.setItem(CookieName.UserID, "one-day", {
189
+ path: new Route("/"),
190
+ maxAgeInDays: 1,
191
+ });
192
+
193
+ expect(lastWriteFor(CookieName.UserID)).toContain("Max-Age=86400000");
194
+ });
195
+
196
+ it("adds the HttpOnly attribute when requested, which browsers then refuse to store from script", () => {
197
+ Cookie.setItem(CookieName.Token, "secret", {
198
+ path: new Route("/"),
199
+ httpOnly: true,
200
+ });
201
+
202
+ expect(lastWriteFor(CookieName.Token)).toContain("HttpOnly");
203
+ // document.cookie cannot create HttpOnly cookies, so nothing is stored.
204
+ expect(readRawJar()[CookieName.Token]).toBeUndefined();
205
+ expect(Cookie.exists(CookieName.Token)).toBe(false);
206
+ });
207
+
208
+ it("JSON-serializes plain objects and getItem returns an equal object", () => {
209
+ const value: JSONObject = { a: 1, nested: { b: "two" }, list: [1, 2] };
210
+
211
+ Cookie.setItem(CookieName.UserID, value);
212
+
213
+ expect(JSON.parse(readRawJar()[CookieName.UserID] as string)).toEqual(
214
+ value,
215
+ );
216
+ expect(Cookie.getItem(CookieName.UserID)).toEqual(value);
217
+ });
218
+
219
+ it("serializes an Email value object into its typed JSON form", () => {
220
+ Cookie.setItem(CookieName.Email, new Email("jane@example.com"));
221
+
222
+ const stored: JSONObject = JSON.parse(
223
+ readRawJar()[CookieName.Email] as string,
224
+ ) as JSONObject;
225
+
226
+ expect(stored["_type"]).toBe("Email");
227
+ expect(stored["value"]).toBe("jane@example.com");
228
+ });
229
+
230
+ it("serializes a URL value object into its typed JSON form", () => {
231
+ Cookie.setItem(
232
+ CookieName.UserID,
233
+ URL.fromString("https://oneuptime.com/dashboard"),
234
+ );
235
+
236
+ const stored: JSONObject = JSON.parse(
237
+ readRawJar()[CookieName.UserID] as string,
238
+ ) as JSONObject;
239
+
240
+ expect(stored["_type"]).toBe("URL");
241
+ expect(stored["value"]).toBe("https://oneuptime.com/dashboard");
242
+ });
243
+
244
+ it("accepts arbitrary string keys as well as CookieName members", () => {
245
+ Cookie.setItem("custom-cookie", "custom-value");
246
+
247
+ expect(readRawJar()["custom-cookie"]).toBe("custom-value");
248
+ });
249
+
250
+ it("overwrites a previous value for the same key and path", () => {
251
+ Cookie.setItem(CookieName.UserID, "first");
252
+ Cookie.setItem(CookieName.UserID, "second");
253
+
254
+ expect(readRawJar()[CookieName.UserID]).toBe("second");
255
+ expect(Cookie.getItem(CookieName.UserID)).toBe("second");
256
+ });
257
+ });
258
+
259
+ describe("getItem", () => {
260
+ it("returns undefined for a cookie that does not exist", () => {
261
+ expect(Cookie.getItem(CookieName.UserID)).toBeUndefined();
262
+ });
263
+
264
+ it("returns non-JSON strings as-is", () => {
265
+ document.cookie = `${CookieName.UserID}=plain-text; path=/`;
266
+
267
+ expect(Cookie.getItem(CookieName.UserID)).toBe("plain-text");
268
+ });
269
+
270
+ it("parses JSON primitives stored in the cookie", () => {
271
+ document.cookie = `${CookieName.IsMasterAdmin}=true; path=/`;
272
+ document.cookie = `${CookieName.ProfilePicID}=42; path=/`;
273
+
274
+ expect(Cookie.getItem(CookieName.IsMasterAdmin)).toBe(true);
275
+ expect(Cookie.getItem(CookieName.ProfilePicID)).toBe(42);
276
+ });
277
+
278
+ it("returns falsy parsed values without attempting to deserialize them", () => {
279
+ document.cookie = `${CookieName.IsMasterAdmin}=false; path=/`;
280
+ document.cookie = `${CookieName.ProfilePicID}=0; path=/`;
281
+
282
+ expect(Cookie.getItem(CookieName.IsMasterAdmin)).toBe(false);
283
+ expect(Cookie.getItem(CookieName.ProfilePicID)).toBe(0);
284
+ });
285
+
286
+ it("decodes percent-encoded cookie values written by the server", () => {
287
+ document.cookie = `${CookieName.Email}=${encodeURIComponent(
288
+ "jane+test@example.com",
289
+ )}; path=/`;
290
+
291
+ expect(Cookie.getItem(CookieName.Email)).toBe("jane+test@example.com");
292
+ });
293
+
294
+ it("strips the express 'j:' prefix from JSON cookies", () => {
295
+ document.cookie = `${CookieName.UserID}=${encodeURIComponent(
296
+ 'j:{"id":"abc"}',
297
+ )}; path=/`;
298
+
299
+ expect(Cookie.getItem(CookieName.UserID)).toEqual({ id: "abc" });
300
+ });
301
+
302
+ it("returns the typed JSON (not a rehydrated instance) for a stored Email", () => {
303
+ Cookie.setItem(CookieName.Email, new Email("jane@example.com"));
304
+
305
+ const value: JSONValue = Cookie.getItem(CookieName.Email);
306
+
307
+ /*
308
+ * universal-cookie already JSON.parses the value, so getItem's own
309
+ * JSON5 parse of `value.toString()` ("[object Object]") throws and the
310
+ * raw object is returned without deserializeValue being applied.
311
+ */
312
+ expect(value).toEqual({ _type: "Email", value: "jane@example.com" });
313
+ expect(value).not.toBeInstanceOf(Email);
314
+ });
315
+ });
316
+
317
+ describe("exists", () => {
318
+ it("is false for a missing cookie and true once set", () => {
319
+ expect(Cookie.exists(CookieName.UserID)).toBe(false);
320
+
321
+ Cookie.setItem(CookieName.UserID, "abc");
322
+
323
+ expect(Cookie.exists(CookieName.UserID)).toBe(true);
324
+ });
325
+
326
+ it("treats a cookie whose parsed value is falsy as not existing", () => {
327
+ document.cookie = `${CookieName.IsMasterAdmin}=false; path=/`;
328
+ document.cookie = `${CookieName.ProfilePicID}=0; path=/`;
329
+ document.cookie = `${CookieName.Name}=; path=/`;
330
+
331
+ expect(readRawJar()[CookieName.IsMasterAdmin]).toBe("false");
332
+ expect(Cookie.exists(CookieName.IsMasterAdmin)).toBe(false);
333
+ expect(Cookie.exists(CookieName.ProfilePicID)).toBe(false);
334
+ expect(Cookie.exists(CookieName.Name)).toBe(false);
335
+ });
336
+ });
337
+
338
+ describe("removeItem", () => {
339
+ it("removes a root-path cookie when called from the root", () => {
340
+ Cookie.setItem(CookieName.UserID, "abc");
341
+ expect(Cookie.exists(CookieName.UserID)).toBe(true);
342
+
343
+ Cookie.removeItem(CookieName.UserID);
344
+
345
+ expect(Cookie.exists(CookieName.UserID)).toBe(false);
346
+ expect(readRawJar()[CookieName.UserID]).toBeUndefined();
347
+
348
+ const write: string = lastWriteFor(CookieName.UserID);
349
+ expect(write).toContain("Max-Age=0");
350
+ expect(write).toContain("Expires=");
351
+ });
352
+
353
+ it("is a no-op for a cookie that does not exist", () => {
354
+ expect(() => {
355
+ Cookie.removeItem(CookieName.UserID);
356
+ }).not.toThrow();
357
+ expect(Cookie.exists(CookieName.UserID)).toBe(false);
358
+ });
359
+
360
+ it("does not send a Path attribute, so it misses root cookies when the page is on a nested route", () => {
361
+ Cookie.setItem(CookieName.UserID, "abc", { path: new Route("/") });
362
+
363
+ window.history.replaceState({}, "", "/dashboard/project/overview");
364
+ Cookie.removeItem(CookieName.UserID);
365
+
366
+ expect(lastWriteFor(CookieName.UserID)).not.toContain("Path=");
367
+ /*
368
+ * Without a Path the browser defaults to the current directory
369
+ * (/dashboard/project), which does not match the "/" cookie, so it
370
+ * survives. Documented here as current behaviour.
371
+ */
372
+ expect(readRawJar()[CookieName.UserID]).toBe("abc");
373
+ });
374
+
375
+ it("leaves other cookies intact", () => {
376
+ Cookie.setItem(CookieName.UserID, "abc");
377
+ Cookie.setItem(CookieName.Name, "Jane");
378
+
379
+ Cookie.removeItem(CookieName.UserID);
380
+
381
+ expect(Cookie.exists(CookieName.UserID)).toBe(false);
382
+ expect(Cookie.getItem(CookieName.Name)).toBe("Jane");
383
+ });
384
+ });
385
+
386
+ describe("clearAllCookies", () => {
387
+ it("removes every cookie named in the CookieName enum", () => {
388
+ for (const name of Object.values(CookieName)) {
389
+ Cookie.setItem(name, `value-${name}`);
390
+ }
391
+
392
+ for (const name of Object.values(CookieName)) {
393
+ expect(Cookie.exists(name)).toBe(true);
394
+ }
395
+
396
+ Cookie.clearAllCookies();
397
+
398
+ for (const name of Object.values(CookieName)) {
399
+ expect(Cookie.exists(name)).toBe(false);
400
+ }
401
+ expect(readRawJar()).toEqual({});
402
+ });
403
+
404
+ it("clears root-path cookies even when invoked from a nested route", () => {
405
+ Cookie.setItem(CookieName.Token, "t");
406
+ Cookie.setItem(CookieName.RefreshToken, "r");
407
+
408
+ window.history.replaceState({}, "", "/dashboard/project/overview");
409
+ Cookie.clearAllCookies();
410
+
411
+ expect(readRawJar()[CookieName.Token]).toBeUndefined();
412
+ expect(readRawJar()[CookieName.RefreshToken]).toBeUndefined();
413
+
414
+ for (const name of Object.values(CookieName)) {
415
+ expect(lastWriteFor(name)).toContain("Path=/");
416
+ }
417
+ });
418
+
419
+ it("does not remove cookies outside the CookieName enum", () => {
420
+ Cookie.setItem("third-party-cookie", "keep-me");
421
+ Cookie.setItem(CookieName.UserID, "abc");
422
+
423
+ Cookie.clearAllCookies();
424
+
425
+ expect(readRawJar()["third-party-cookie"]).toBe("keep-me");
426
+ expect(Cookie.exists(CookieName.UserID)).toBe(false);
427
+ });
428
+
429
+ it("does not remove enum cookies scoped to a non-root path", () => {
430
+ Cookie.setItem(CookieName.Timezone, "UTC", {
431
+ path: new Route("/dashboard"),
432
+ });
433
+
434
+ Cookie.clearAllCookies();
435
+
436
+ window.history.replaceState({}, "", "/dashboard/home");
437
+ expect(readRawJar()[CookieName.Timezone]).toBe("UTC");
438
+ });
439
+ });
440
+ });