@oneuptime/common 12.0.28 → 12.0.30

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 (367) hide show
  1. package/Models/DatabaseModels/DashboardDomain.ts +43 -0
  2. package/Models/DatabaseModels/Index.ts +11 -0
  3. package/Models/DatabaseModels/MonitorTemplate.ts +15 -3
  4. package/Models/DatabaseModels/OnCallDutyPolicySchedule.ts +43 -0
  5. package/Models/DatabaseModels/OnCallDutyPolicyScheduleCalendarFeed.ts +662 -0
  6. package/Models/DatabaseModels/ProjectOnCallCalendarFeed.ts +584 -0
  7. package/Models/DatabaseModels/StatusPageDomain.ts +43 -0
  8. package/Models/DatabaseModels/UserOnCallCalendarFeed.ts +546 -0
  9. package/Models/DatabaseModels/UserOnCallShiftReminder.ts +231 -0
  10. package/Models/DatabaseModels/UserOnCallShiftReminderLog.ts +331 -0
  11. package/Server/API/DashboardDomainAPI.ts +74 -0
  12. package/Server/API/MicrosoftTeamsAPI.ts +81 -180
  13. package/Server/API/OnCallCalendarAPI.ts +2194 -0
  14. package/Server/API/StatusPageDomainAPI.ts +74 -0
  15. package/Server/EnvironmentConfig.ts +138 -0
  16. package/Server/Infrastructure/OnCallCalendarFeedCache.ts +1050 -0
  17. package/Server/Infrastructure/Postgres/SchemaMigrations/1790200000000-AllowNullMonitorNameOnMonitorTemplate.ts +43 -0
  18. package/Server/Infrastructure/Postgres/SchemaMigrations/1790300000000-AddCertificateReissueRequestedAtToDomains.ts +40 -0
  19. package/Server/Infrastructure/Postgres/SchemaMigrations/1790400000000-AddOnCallCalendarFeeds.ts +253 -0
  20. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +6 -0
  21. package/Server/Middleware/OnCallCalendarFeedRateLimit.ts +487 -0
  22. package/Server/Middleware/ProjectAuthorization.ts +6 -1
  23. package/Server/Services/DashboardDomainService.ts +131 -0
  24. package/Server/Services/Index.ts +12 -0
  25. package/Server/Services/LogPipelineProcessorService.ts +88 -0
  26. package/Server/Services/MonitorTemplateService.ts +70 -11
  27. package/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.ts +32 -0
  28. package/Server/Services/OnCallDutyPolicyScheduleCalendarFeedService.ts +260 -0
  29. package/Server/Services/OnCallDutyPolicyScheduleLayerService.ts +70 -3
  30. package/Server/Services/OnCallDutyPolicyScheduleLayerUserService.ts +138 -3
  31. package/Server/Services/OnCallDutyPolicyScheduleService.ts +1465 -134
  32. package/Server/Services/OnCallDutyPolicyUserOverrideService.ts +167 -31
  33. package/Server/Services/ProjectOnCallCalendarFeedService.ts +192 -0
  34. package/Server/Services/StatusPageDomainService.ts +163 -3
  35. package/Server/Services/StatusPagePrivateUserSessionService.ts +197 -56
  36. package/Server/Services/TeamMemberService.ts +489 -1
  37. package/Server/Services/TeamService.ts +50 -0
  38. package/Server/Services/UserNotificationSettingService.ts +44 -1
  39. package/Server/Services/UserOnCallCalendarFeedService.ts +159 -0
  40. package/Server/Services/UserOnCallShiftReminderLogService.ts +151 -0
  41. package/Server/Services/UserOnCallShiftReminderService.ts +112 -0
  42. package/Server/Types/Domain.ts +17 -0
  43. package/Server/Utils/APIKey/AccessPermission.ts +24 -0
  44. package/Server/Utils/Greenlock/Greenlock.ts +156 -58
  45. package/Server/Utils/LogPipelineProcessorValidation.ts +112 -0
  46. package/Server/Utils/OnCall/CalendarFeedToken.ts +241 -0
  47. package/Server/Utils/OnCall/OnCallCalendarFeedRenderer.ts +1488 -0
  48. package/Server/Utils/OnCall/OnCallCalendarFeedUrls.ts +230 -0
  49. package/Server/Utils/OnCall/OnCallShiftChangeListeners.ts +227 -0
  50. package/Server/Utils/OnCall/OnCallShiftMaterializer.ts +1127 -0
  51. package/Server/Utils/OnCall/OnCallShiftReminderListener.ts +174 -0
  52. package/Server/Utils/OnCall/OnCallShiftReminderRunner.ts +2584 -0
  53. package/Server/Utils/Response.ts +134 -0
  54. package/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsClient.ts +1094 -45
  55. package/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsPoller.ts +153 -17
  56. package/Server/Utils/StartServer.ts +10 -0
  57. package/Server/Utils/Telemetry/AppMetrics.ts +51 -0
  58. package/Server/Utils/Workspace/MicrosoftTeams/Actions/Alert.ts +23 -11
  59. package/Server/Utils/Workspace/MicrosoftTeams/Actions/Auth.ts +0 -170
  60. package/Server/Utils/Workspace/MicrosoftTeams/Actions/Authorization.ts +158 -0
  61. package/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.ts +23 -11
  62. package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.ts +35 -13
  63. package/Tests/App/Dashboard/MonitorTemplateColumnAndFacet.test.tsx +505 -0
  64. package/Tests/App/Dashboard/OnCallCalendarFeedLinks.test.tsx +229 -0
  65. package/Tests/App/Dashboard/OnCallCalendarFeedPlanGate.test.tsx +489 -0
  66. package/Tests/App/Dashboard/OnCallCalendarFeedSideMenus.test.tsx +149 -0
  67. package/Tests/App/Dashboard/OnCallCalendarFeedUtil.test.ts +855 -0
  68. package/Tests/App/Dashboard/OnCallPersonalCalendarFeed.test.tsx +1209 -0
  69. package/Tests/App/Dashboard/OnCallSharedCalendarFeedCard.test.tsx +1019 -0
  70. package/Tests/App/Dashboard/OnCallShiftRemindersAndUpcomingShifts.test.tsx +655 -0
  71. package/Tests/App/Dashboard/UserSettingsSetupChecklistModel.test.ts +73 -0
  72. package/Tests/App/StatusPage/StatusPageLoginCodeBootstrap.test.ts +106 -0
  73. package/Tests/App/StatusPage/StatusPageLoginCodeUtil.test.ts +84 -0
  74. package/Tests/App/StatusPage/StatusPageRedirectSafety.test.ts +119 -0
  75. package/Tests/Models/MonitorTemplateMonitorNameColumn.test.ts +258 -0
  76. package/Tests/Models/OnCallCalendarFeedModels.test.ts +642 -0
  77. package/Tests/Models/OnCallDutyPolicyScheduleCalendarFeed.test.ts +288 -0
  78. package/Tests/Models/OnCallDutyPolicyScheduleShiftConfigVersion.test.ts +88 -0
  79. package/Tests/Models/UserOnCallShiftReminderModels.test.ts +368 -0
  80. package/Tests/Server/API/CustomDomainReissueSslAPI.test.ts +469 -0
  81. package/Tests/Server/API/Helpers.ts +8 -0
  82. package/Tests/Server/API/MicrosoftTeamsBotMessagesEndpoint.test.ts +729 -0
  83. package/Tests/Server/API/MicrosoftTeamsBotTestEndpoint.test.ts +26 -0
  84. package/Tests/Server/API/MicrosoftTeamsLegacyWebhookRemoval.test.ts +402 -0
  85. package/Tests/Server/API/OnCallCalendarAPI.test.ts +4461 -0
  86. package/Tests/Server/EnvironmentConfigOnCallCalendarFeed.test.ts +357 -0
  87. package/Tests/Server/Infrastructure/OnCallCalendarFeedCache.test.ts +1589 -0
  88. package/Tests/Server/Infrastructure/Postgres/AddOnCallCalendarFeedsMigration.test.ts +369 -0
  89. package/Tests/Server/Middleware/OnCallCalendarFeedRateLimit.test.ts +1365 -0
  90. package/Tests/Server/Middleware/ProjectAuthorizationApiKeyMiddleware.test.ts +4 -0
  91. package/Tests/Server/Services/AddCertificateReissueRequestedAtToDomainsMigration.test.ts +287 -0
  92. package/Tests/Server/Services/CustomDomainCertificateReissue.test.ts +477 -0
  93. package/Tests/Server/Services/FeedRetentionConsistency.test.ts +70 -0
  94. package/Tests/Server/Services/LogPipelineProcessorSaveValidation.test.ts +249 -0
  95. package/Tests/Server/Services/MonitorTemplateServiceBulkSync.test.ts +549 -0
  96. package/Tests/Server/Services/MonitorTemplateServiceNetworkDeviceSync.test.ts +16 -3
  97. package/Tests/Server/Services/NetworkDeviceAutoImportRuleEngineService.test.ts +57 -0
  98. package/Tests/Server/Services/OnCallCalendarFeedServices.test.ts +1103 -0
  99. package/Tests/Server/Services/OnCallDutyPolicyScheduleResolver.test.ts +1037 -0
  100. package/Tests/Server/Services/OnCallShiftConfigPropagation.test.ts +1270 -0
  101. package/Tests/Server/Services/SecurityEventLastErrorColumnWidth.test.ts +151 -15
  102. package/Tests/Server/Services/StatusPagePrivateUserSessionService.test.ts +587 -0
  103. package/Tests/Server/Services/TeamDeleteMemberCleanup.test.ts +156 -0
  104. package/Tests/Server/Services/TeamMemberOnCallCleanup.test.ts +755 -0
  105. package/Tests/Server/Services/UserNotificationSettingShiftReminderDefaults.test.ts +267 -0
  106. package/Tests/Server/Services/UserOnCallShiftReminderServices.test.ts +583 -0
  107. package/Tests/Server/Types/Database/Permissions/ApiKeyFileAccess.test.ts +286 -0
  108. package/Tests/Server/Types/Database/Permissions/MonitorTemplateColumnAccess.test.ts +328 -0
  109. package/Tests/Server/Types/Database/Permissions/OnCallCalendarFeedPermissions.test.ts +254 -0
  110. package/Tests/Server/Types/Database/QueryHelperFindWithSameTextAndIsNull.test.ts +83 -0
  111. package/Tests/Server/Utils/AI/SRE/ConfidenceSignal.test.ts +377 -0
  112. package/Tests/Server/Utils/APIKey/AccessPermission.test.ts +16 -1
  113. package/Tests/Server/Utils/Greenlock/CertificateRenewalSchedule.test.ts +250 -0
  114. package/Tests/Server/Utils/LogPipelineProcessorValidation.test.ts +198 -0
  115. package/Tests/Server/Utils/OnCall/CalendarFeedToken.test.ts +467 -0
  116. package/Tests/Server/Utils/OnCall/OnCallCalendarFeedRenderer.test.ts +2142 -0
  117. package/Tests/Server/Utils/OnCall/OnCallCalendarFeedUrls.test.ts +278 -0
  118. package/Tests/Server/Utils/OnCall/OnCallResolverTestHarness.ts +440 -0
  119. package/Tests/Server/Utils/OnCall/OnCallShiftChangeListeners.test.ts +314 -0
  120. package/Tests/Server/Utils/OnCall/OnCallShiftMaterializer.test.ts +1502 -0
  121. package/Tests/Server/Utils/OnCall/OnCallShiftReminderListener.test.ts +491 -0
  122. package/Tests/Server/Utils/OnCall/OnCallShiftReminderRunner.test.ts +3088 -0
  123. package/Tests/Server/Utils/OnCall/OnCallShiftReminderTestHarness.ts +910 -0
  124. package/Tests/Server/Utils/ResponseSendCalendarResponse.test.ts +561 -0
  125. package/Tests/Server/Utils/SecurityEvent/ConnectorErrorMessage.test.ts +48 -9
  126. package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsAuth.test.ts +726 -0
  127. package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsClient.test.ts +74 -11
  128. package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsErrorHandling.test.ts +1107 -0
  129. package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsPoller.test.ts +20 -3
  130. package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsPollerFailureTaxonomy.test.ts +51 -11
  131. package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsPollerHardening.test.ts +1246 -0
  132. package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsRequestContract.test.ts +961 -0
  133. package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsResponseParsing.test.ts +653 -0
  134. package/Tests/Server/Utils/StartServerEncryptionSecretWarning.test.ts +64 -0
  135. package/Tests/Server/Utils/Telemetry/AppMetrics.test.ts +29 -0
  136. package/Tests/Server/Utils/Workspace/MicrosoftTeamsActionAuthorization.test.ts +880 -0
  137. package/Tests/Types/API/HTTPResponse.test.ts +175 -0
  138. package/Tests/Types/API/Route.test.ts +36 -4
  139. package/Tests/Types/Calendar/ICalendar.test.ts +488 -0
  140. package/Tests/Types/Database/DatabaseProperty.test.ts +171 -0
  141. package/Tests/Types/DateLocalShortDateTimeString.test.ts +518 -0
  142. package/Tests/Types/DateLocalTimeString.test.ts +259 -0
  143. package/Tests/Types/DateUserPrefers12HourFormat.test.ts +316 -0
  144. package/Tests/Types/NotificationSetting/NotificationSettingEventType.test.ts +53 -0
  145. package/Tests/Types/OnCallDutyPolicy/CalendarFeedTestFixtures.ts +310 -0
  146. package/Tests/Types/OnCallDutyPolicy/CalendarFeedWindow.test.ts +205 -0
  147. package/Tests/Types/OnCallDutyPolicy/LayerUtilLayerMetaAndIterationCap.test.ts +458 -0
  148. package/Tests/Types/OnCallDutyPolicy/MaterializedShift.test.ts +197 -0
  149. package/Tests/Types/OnCallDutyPolicy/OnCallCalendarFeedUtil.test.ts +1986 -0
  150. package/Tests/Types/OnCallDutyPolicy/ScheduleShiftUtilGroupKey.test.ts +678 -0
  151. package/Tests/Types/OnCallDutyPolicy/ShiftSeamUtil.test.ts +417 -0
  152. package/Tests/UI/Components/LogsHistogram.test.tsx +41 -2
  153. package/Tests/UI/Components/LogsViewerEmptyStateTimeRange.test.tsx +212 -0
  154. package/Tests/UI/Components/TelemetryChartClockFormat.test.tsx +359 -0
  155. package/Tests/UI/Components/TimeRangePickerClockFormat.test.tsx +422 -0
  156. package/Tests/UI/Components/TimeRangePickerDropdown.test.tsx +146 -8
  157. package/Tests/UI/MicrosoftTeams/MicrosoftTeamsMessagingEndpointGuidance.test.tsx +520 -0
  158. package/Tests/UI/Utils/Breadcrumb/fixtures/RealBreadcrumbTrails.ts +10 -0
  159. package/Tests/UI/Utils/Breadcrumb/fixtures/RealRoutePatterns.ts +2 -0
  160. package/Tests/UI/Utils/Navigation.test.ts +82 -0
  161. package/Tests/Utils/Array.test.ts +100 -0
  162. package/Tests/Utils/CertificateReissue.test.ts +225 -0
  163. package/Tests/Utils/Grok/Grok.test.ts +492 -0
  164. package/Tests/Utils/Monitor/NetworkDeviceMonitorTemplateUtil.test.ts +181 -13
  165. package/Types/API/Route.ts +20 -5
  166. package/Types/Calendar/ICalendar.ts +442 -0
  167. package/Types/Date.ts +143 -13
  168. package/Types/Email/EmailTemplateType.ts +2 -0
  169. package/Types/NotificationSetting/NotificationSettingEventType.ts +4 -0
  170. package/Types/OnCallDutyPolicy/CalendarFeedWindow.ts +140 -0
  171. package/Types/OnCallDutyPolicy/Layer.ts +190 -35
  172. package/Types/OnCallDutyPolicy/MaterializedShift.ts +274 -0
  173. package/Types/OnCallDutyPolicy/OnCallCalendarFeedUtil.ts +1415 -0
  174. package/Types/OnCallDutyPolicy/ScheduleShiftUtil.ts +159 -4
  175. package/Types/OnCallDutyPolicy/ShiftSeamUtil.ts +106 -0
  176. package/Types/Rum/SessionReplay.ts +62 -1
  177. package/UI/Components/Date/TimeRangePickerDropdown.tsx +9 -5
  178. package/UI/Components/LogsViewer/LogsViewer.tsx +12 -7
  179. package/UI/Components/LogsViewer/components/HistogramTooltip.tsx +18 -17
  180. package/UI/Components/LogsViewer/components/LogsAnalyticsView.tsx +21 -28
  181. package/UI/Components/LogsViewer/components/LogsHistogram.tsx +2 -4
  182. package/UI/Components/TelemetryViewer/components/TelemetryHistogram.tsx +2 -4
  183. package/UI/Components/TelemetryViewer/components/TelemetryHistogramTooltip.tsx +17 -16
  184. package/UI/Utils/Navigation.ts +42 -0
  185. package/Utils/Array.ts +37 -0
  186. package/Utils/CertificateReissue.ts +128 -0
  187. package/Utils/Grok/Grok.ts +461 -0
  188. package/Utils/Grok/GrokPatterns.ts +118 -0
  189. package/Utils/Monitor/NetworkDeviceMonitorTemplateUtil.ts +58 -6
  190. package/build/dist/Models/DatabaseModels/DashboardDomain.js +44 -0
  191. package/build/dist/Models/DatabaseModels/DashboardDomain.js.map +1 -1
  192. package/build/dist/Models/DatabaseModels/Index.js +11 -0
  193. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  194. package/build/dist/Models/DatabaseModels/MonitorTemplate.js +17 -4
  195. package/build/dist/Models/DatabaseModels/MonitorTemplate.js.map +1 -1
  196. package/build/dist/Models/DatabaseModels/OnCallDutyPolicySchedule.js +44 -0
  197. package/build/dist/Models/DatabaseModels/OnCallDutyPolicySchedule.js.map +1 -1
  198. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyScheduleCalendarFeed.js +699 -0
  199. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyScheduleCalendarFeed.js.map +1 -0
  200. package/build/dist/Models/DatabaseModels/ProjectOnCallCalendarFeed.js +620 -0
  201. package/build/dist/Models/DatabaseModels/ProjectOnCallCalendarFeed.js.map +1 -0
  202. package/build/dist/Models/DatabaseModels/StatusPageDomain.js +44 -0
  203. package/build/dist/Models/DatabaseModels/StatusPageDomain.js.map +1 -1
  204. package/build/dist/Models/DatabaseModels/UserOnCallCalendarFeed.js +585 -0
  205. package/build/dist/Models/DatabaseModels/UserOnCallCalendarFeed.js.map +1 -0
  206. package/build/dist/Models/DatabaseModels/UserOnCallShiftReminder.js +247 -0
  207. package/build/dist/Models/DatabaseModels/UserOnCallShiftReminder.js.map +1 -0
  208. package/build/dist/Models/DatabaseModels/UserOnCallShiftReminderLog.js +355 -0
  209. package/build/dist/Models/DatabaseModels/UserOnCallShiftReminderLog.js.map +1 -0
  210. package/build/dist/Server/API/DashboardDomainAPI.js +43 -1
  211. package/build/dist/Server/API/DashboardDomainAPI.js.map +1 -1
  212. package/build/dist/Server/API/MicrosoftTeamsAPI.js +74 -118
  213. package/build/dist/Server/API/MicrosoftTeamsAPI.js.map +1 -1
  214. package/build/dist/Server/API/OnCallCalendarAPI.js +1371 -0
  215. package/build/dist/Server/API/OnCallCalendarAPI.js.map +1 -0
  216. package/build/dist/Server/API/StatusPageDomainAPI.js +43 -1
  217. package/build/dist/Server/API/StatusPageDomainAPI.js.map +1 -1
  218. package/build/dist/Server/EnvironmentConfig.js +102 -0
  219. package/build/dist/Server/EnvironmentConfig.js.map +1 -1
  220. package/build/dist/Server/Infrastructure/OnCallCalendarFeedCache.js +663 -0
  221. package/build/dist/Server/Infrastructure/OnCallCalendarFeedCache.js.map +1 -0
  222. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790200000000-AllowNullMonitorNameOnMonitorTemplate.js +34 -0
  223. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790200000000-AllowNullMonitorNameOnMonitorTemplate.js.map +1 -0
  224. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790300000000-AddCertificateReissueRequestedAtToDomains.js +28 -0
  225. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790300000000-AddCertificateReissueRequestedAtToDomains.js.map +1 -0
  226. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790400000000-AddOnCallCalendarFeeds.js +103 -0
  227. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790400000000-AddOnCallCalendarFeeds.js.map +1 -0
  228. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +6 -0
  229. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  230. package/build/dist/Server/Middleware/OnCallCalendarFeedRateLimit.js +342 -0
  231. package/build/dist/Server/Middleware/OnCallCalendarFeedRateLimit.js.map +1 -0
  232. package/build/dist/Server/Middleware/ProjectAuthorization.js +6 -1
  233. package/build/dist/Server/Middleware/ProjectAuthorization.js.map +1 -1
  234. package/build/dist/Server/Services/DashboardDomainService.js +104 -0
  235. package/build/dist/Server/Services/DashboardDomainService.js.map +1 -1
  236. package/build/dist/Server/Services/Index.js +12 -0
  237. package/build/dist/Server/Services/Index.js.map +1 -1
  238. package/build/dist/Server/Services/LogPipelineProcessorService.js +65 -0
  239. package/build/dist/Server/Services/LogPipelineProcessorService.js.map +1 -1
  240. package/build/dist/Server/Services/MonitorTemplateService.js +57 -11
  241. package/build/dist/Server/Services/MonitorTemplateService.js.map +1 -1
  242. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js +20 -0
  243. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js.map +1 -1
  244. package/build/dist/Server/Services/OnCallDutyPolicyScheduleCalendarFeedService.js +219 -0
  245. package/build/dist/Server/Services/OnCallDutyPolicyScheduleCalendarFeedService.js.map +1 -0
  246. package/build/dist/Server/Services/OnCallDutyPolicyScheduleLayerService.js +47 -3
  247. package/build/dist/Server/Services/OnCallDutyPolicyScheduleLayerService.js.map +1 -1
  248. package/build/dist/Server/Services/OnCallDutyPolicyScheduleLayerUserService.js +112 -3
  249. package/build/dist/Server/Services/OnCallDutyPolicyScheduleLayerUserService.js.map +1 -1
  250. package/build/dist/Server/Services/OnCallDutyPolicyScheduleService.js +955 -9
  251. package/build/dist/Server/Services/OnCallDutyPolicyScheduleService.js.map +1 -1
  252. package/build/dist/Server/Services/OnCallDutyPolicyUserOverrideService.js +93 -6
  253. package/build/dist/Server/Services/OnCallDutyPolicyUserOverrideService.js.map +1 -1
  254. package/build/dist/Server/Services/ProjectOnCallCalendarFeedService.js +157 -0
  255. package/build/dist/Server/Services/ProjectOnCallCalendarFeedService.js.map +1 -0
  256. package/build/dist/Server/Services/StatusPageDomainService.js +132 -3
  257. package/build/dist/Server/Services/StatusPageDomainService.js.map +1 -1
  258. package/build/dist/Server/Services/StatusPagePrivateUserSessionService.js +112 -32
  259. package/build/dist/Server/Services/StatusPagePrivateUserSessionService.js.map +1 -1
  260. package/build/dist/Server/Services/TeamMemberService.js +396 -1
  261. package/build/dist/Server/Services/TeamMemberService.js.map +1 -1
  262. package/build/dist/Server/Services/TeamService.js +43 -0
  263. package/build/dist/Server/Services/TeamService.js.map +1 -1
  264. package/build/dist/Server/Services/UserNotificationSettingService.js +26 -1
  265. package/build/dist/Server/Services/UserNotificationSettingService.js.map +1 -1
  266. package/build/dist/Server/Services/UserOnCallCalendarFeedService.js +140 -0
  267. package/build/dist/Server/Services/UserOnCallCalendarFeedService.js.map +1 -0
  268. package/build/dist/Server/Services/UserOnCallShiftReminderLogService.js +116 -0
  269. package/build/dist/Server/Services/UserOnCallShiftReminderLogService.js.map +1 -0
  270. package/build/dist/Server/Services/UserOnCallShiftReminderService.js +92 -0
  271. package/build/dist/Server/Services/UserOnCallShiftReminderService.js.map +1 -0
  272. package/build/dist/Server/Types/Domain.js +16 -0
  273. package/build/dist/Server/Types/Domain.js.map +1 -1
  274. package/build/dist/Server/Utils/APIKey/AccessPermission.js +24 -0
  275. package/build/dist/Server/Utils/APIKey/AccessPermission.js.map +1 -1
  276. package/build/dist/Server/Utils/Greenlock/Greenlock.js +110 -35
  277. package/build/dist/Server/Utils/Greenlock/Greenlock.js.map +1 -1
  278. package/build/dist/Server/Utils/LogPipelineProcessorValidation.js +77 -0
  279. package/build/dist/Server/Utils/LogPipelineProcessorValidation.js.map +1 -0
  280. package/build/dist/Server/Utils/OnCall/CalendarFeedToken.js +161 -0
  281. package/build/dist/Server/Utils/OnCall/CalendarFeedToken.js.map +1 -0
  282. package/build/dist/Server/Utils/OnCall/OnCallCalendarFeedRenderer.js +983 -0
  283. package/build/dist/Server/Utils/OnCall/OnCallCalendarFeedRenderer.js.map +1 -0
  284. package/build/dist/Server/Utils/OnCall/OnCallCalendarFeedUrls.js +155 -0
  285. package/build/dist/Server/Utils/OnCall/OnCallCalendarFeedUrls.js.map +1 -0
  286. package/build/dist/Server/Utils/OnCall/OnCallShiftChangeListeners.js +145 -0
  287. package/build/dist/Server/Utils/OnCall/OnCallShiftChangeListeners.js.map +1 -0
  288. package/build/dist/Server/Utils/OnCall/OnCallShiftMaterializer.js +752 -0
  289. package/build/dist/Server/Utils/OnCall/OnCallShiftMaterializer.js.map +1 -0
  290. package/build/dist/Server/Utils/OnCall/OnCallShiftReminderListener.js +92 -0
  291. package/build/dist/Server/Utils/OnCall/OnCallShiftReminderListener.js.map +1 -0
  292. package/build/dist/Server/Utils/OnCall/OnCallShiftReminderRunner.js +1786 -0
  293. package/build/dist/Server/Utils/OnCall/OnCallShiftReminderRunner.js.map +1 -0
  294. package/build/dist/Server/Utils/Response.js +97 -0
  295. package/build/dist/Server/Utils/Response.js.map +1 -1
  296. package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsClient.js +777 -36
  297. package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsClient.js.map +1 -1
  298. package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsPoller.js +108 -17
  299. package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsPoller.js.map +1 -1
  300. package/build/dist/Server/Utils/StartServer.js +9 -1
  301. package/build/dist/Server/Utils/StartServer.js.map +1 -1
  302. package/build/dist/Server/Utils/Telemetry/AppMetrics.js +41 -0
  303. package/build/dist/Server/Utils/Telemetry/AppMetrics.js.map +1 -1
  304. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Alert.js +17 -6
  305. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Alert.js.map +1 -1
  306. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Auth.js +0 -159
  307. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Auth.js.map +1 -1
  308. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Authorization.js +128 -0
  309. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Authorization.js.map +1 -0
  310. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.js +17 -6
  311. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.js.map +1 -1
  312. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js +25 -13
  313. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js.map +1 -1
  314. package/build/dist/Types/API/Route.js +16 -5
  315. package/build/dist/Types/API/Route.js.map +1 -1
  316. package/build/dist/Types/Calendar/ICalendar.js +290 -0
  317. package/build/dist/Types/Calendar/ICalendar.js.map +1 -0
  318. package/build/dist/Types/Date.js +115 -13
  319. package/build/dist/Types/Date.js.map +1 -1
  320. package/build/dist/Types/Email/EmailTemplateType.js +2 -0
  321. package/build/dist/Types/Email/EmailTemplateType.js.map +1 -1
  322. package/build/dist/Types/NotificationSetting/NotificationSettingEventType.js +3 -0
  323. package/build/dist/Types/NotificationSetting/NotificationSettingEventType.js.map +1 -1
  324. package/build/dist/Types/OnCallDutyPolicy/CalendarFeedWindow.js +97 -0
  325. package/build/dist/Types/OnCallDutyPolicy/CalendarFeedWindow.js.map +1 -0
  326. package/build/dist/Types/OnCallDutyPolicy/Layer.js +113 -19
  327. package/build/dist/Types/OnCallDutyPolicy/Layer.js.map +1 -1
  328. package/build/dist/Types/OnCallDutyPolicy/MaterializedShift.js +134 -0
  329. package/build/dist/Types/OnCallDutyPolicy/MaterializedShift.js.map +1 -0
  330. package/build/dist/Types/OnCallDutyPolicy/OnCallCalendarFeedUtil.js +800 -0
  331. package/build/dist/Types/OnCallDutyPolicy/OnCallCalendarFeedUtil.js.map +1 -0
  332. package/build/dist/Types/OnCallDutyPolicy/ScheduleShiftUtil.js +97 -3
  333. package/build/dist/Types/OnCallDutyPolicy/ScheduleShiftUtil.js.map +1 -1
  334. package/build/dist/Types/OnCallDutyPolicy/ShiftSeamUtil.js +77 -0
  335. package/build/dist/Types/OnCallDutyPolicy/ShiftSeamUtil.js.map +1 -0
  336. package/build/dist/Types/Rum/SessionReplay.js +38 -0
  337. package/build/dist/Types/Rum/SessionReplay.js.map +1 -1
  338. package/build/dist/UI/Components/Date/TimeRangePickerDropdown.js +9 -5
  339. package/build/dist/UI/Components/Date/TimeRangePickerDropdown.js.map +1 -1
  340. package/build/dist/UI/Components/LogsViewer/LogsViewer.js +12 -7
  341. package/build/dist/UI/Components/LogsViewer/LogsViewer.js.map +1 -1
  342. package/build/dist/UI/Components/LogsViewer/components/HistogramTooltip.js +15 -14
  343. package/build/dist/UI/Components/LogsViewer/components/HistogramTooltip.js.map +1 -1
  344. package/build/dist/UI/Components/LogsViewer/components/LogsAnalyticsView.js +17 -22
  345. package/build/dist/UI/Components/LogsViewer/components/LogsAnalyticsView.js.map +1 -1
  346. package/build/dist/UI/Components/LogsViewer/components/LogsHistogram.js +2 -4
  347. package/build/dist/UI/Components/LogsViewer/components/LogsHistogram.js.map +1 -1
  348. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryHistogram.js +2 -4
  349. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryHistogram.js.map +1 -1
  350. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryHistogramTooltip.js +15 -14
  351. package/build/dist/UI/Components/TelemetryViewer/components/TelemetryHistogramTooltip.js.map +1 -1
  352. package/build/dist/UI/Utils/Navigation.js +30 -0
  353. package/build/dist/UI/Utils/Navigation.js.map +1 -1
  354. package/build/dist/Utils/Array.js +25 -0
  355. package/build/dist/Utils/Array.js.map +1 -1
  356. package/build/dist/Utils/CertificateReissue.js +97 -0
  357. package/build/dist/Utils/CertificateReissue.js.map +1 -0
  358. package/build/dist/Utils/Grok/Grok.js +324 -0
  359. package/build/dist/Utils/Grok/Grok.js.map +1 -0
  360. package/build/dist/Utils/Grok/GrokPatterns.js +112 -0
  361. package/build/dist/Utils/Grok/GrokPatterns.js.map +1 -0
  362. package/build/dist/Utils/Monitor/NetworkDeviceMonitorTemplateUtil.js +63 -3
  363. package/build/dist/Utils/Monitor/NetworkDeviceMonitorTemplateUtil.js.map +1 -1
  364. package/package.json +1 -1
  365. package/UI/Utils/JsonWebToken.ts +0 -14
  366. package/build/dist/UI/Utils/JsonWebToken.js +0 -10
  367. package/build/dist/UI/Utils/JsonWebToken.js.map +0 -1
@@ -270,6 +270,42 @@ abstract class Navigation {
270
270
  this.navigateHook(-1);
271
271
  }
272
272
 
273
+ /**
274
+ * Return whether a value is an unambiguous same-origin path. Redirect
275
+ * targets must be paths rather than URLs so schemes, protocol-relative
276
+ * values, and backslash authority tricks can never reach a browser
277
+ * navigation sink.
278
+ */
279
+ public static isSafeInternalRoute(route: Route | string): boolean {
280
+ const routeValue: string = route.toString();
281
+
282
+ if (
283
+ !routeValue.startsWith("/") ||
284
+ routeValue.startsWith("//") ||
285
+ routeValue.includes("\\")
286
+ ) {
287
+ return false;
288
+ }
289
+
290
+ try {
291
+ /*
292
+ * URL accepts characters that Route deliberately rejects. Validate the
293
+ * exact sink contract here so a value marked safe cannot crash later
294
+ * when a caller constructs the Route used for navigation.
295
+ */
296
+ new Route(routeValue);
297
+
298
+ const parsedUrl: globalThis.URL = new window.URL(
299
+ routeValue,
300
+ window.location.origin,
301
+ );
302
+
303
+ return parsedUrl.origin === window.location.origin;
304
+ } catch {
305
+ return false;
306
+ }
307
+ }
308
+
273
309
  public static navigate(
274
310
  to: Route | URL,
275
311
  options?: {
@@ -288,6 +324,12 @@ abstract class Navigation {
288
324
  }
289
325
 
290
326
  if (options?.forceNavigate && to instanceof Route) {
327
+ if (!this.isSafeInternalRoute(to)) {
328
+ throw new BadDataException(
329
+ `Cannot force navigate to a non-internal route: ${finalUrl}`,
330
+ );
331
+ }
332
+
291
333
  window.location.href = finalUrl;
292
334
  return;
293
335
  }
package/Utils/Array.ts CHANGED
@@ -1,6 +1,43 @@
1
1
  import ObjectID from "../Types/ObjectID";
2
2
 
3
3
  export default class ArrayUtil {
4
+ /*
5
+ * Run handler over every item, at most `concurrency` of them in flight.
6
+ *
7
+ * For work that is spent waiting on the network rather than on the CPU -
8
+ * walking a list of customer domains and making a request against each -
9
+ * awaiting one at a time leaves the caller idle for almost all of its wall
10
+ * clock, and a single slow item delays every item behind it.
11
+ *
12
+ * Items are handed out in order, so a caller that has sorted by urgency still
13
+ * gets the urgent ones started first. handler is expected to deal with its
14
+ * own failures: as with Promise.all, the first rejection is what the caller
15
+ * sees, and it does not stop work already in flight.
16
+ */
17
+ public static async forEachWithConcurrency<T>(
18
+ array: Array<T>,
19
+ concurrency: number,
20
+ handler: (item: T) => Promise<void>,
21
+ ): Promise<void> {
22
+ let nextIndex: number = 0;
23
+
24
+ const worker: () => Promise<void> = async (): Promise<void> => {
25
+ while (nextIndex < array.length) {
26
+ const index: number = nextIndex++;
27
+ await handler(array[index] as T);
28
+ }
29
+ };
30
+
31
+ await Promise.all(
32
+ Array.from(
33
+ { length: Math.max(1, Math.min(concurrency, array.length)) },
34
+ (): Promise<void> => {
35
+ return worker();
36
+ },
37
+ ),
38
+ );
39
+ }
40
+
4
41
  public static mergeStringArrays(
5
42
  array1: Array<string>,
6
43
  array2: Array<string>,
@@ -0,0 +1,128 @@
1
+ import OneUptimeDate from "../Types/Date";
2
+
3
+ /*
4
+ * The cooldown that sits behind the "Reissue SSL Certificate" button on a
5
+ * custom domain.
6
+ *
7
+ * OneUptime orders certificates from Let's Encrypt against a single ACME
8
+ * account shared by every customer on the installation, so a button that any
9
+ * customer can press is a button that spends everybody's allowance. Two of
10
+ * Let's Encrypt's limits are the ones this guards:
11
+ *
12
+ * - 5 failed validations per account, per hostname, per hour. A domain whose
13
+ * CNAME is half-broken fails validation every single time, so an
14
+ * unthrottled button is a way to burn that hostname's whole hourly budget
15
+ * in seconds - including the budget the automated renewal cron needs.
16
+ * - 5 duplicate certificates per week for the same exact set of hostnames.
17
+ * A reissue is by definition a duplicate certificate: same hostname, no
18
+ * change. This is the limit a determined presser reaches second.
19
+ *
20
+ * Deliberately pure and synchronous, and deliberately in Common/Utils rather
21
+ * than Common/Server: the dashboard renders the very same countdown the API
22
+ * will enforce, so the button explains itself before it is pressed instead of
23
+ * only after the request comes back rejected.
24
+ *
25
+ * The cooldown is keyed off when a reissue was REQUESTED, not when one
26
+ * succeeded. A request that fails at the CA still cost a validation attempt,
27
+ * and a failing domain is exactly the domain a frustrated customer presses
28
+ * again - so a failed attempt must start the clock just as a successful one
29
+ * does.
30
+ */
31
+ export default class CertificateReissueUtil {
32
+ /*
33
+ * Note on the value: 24 hours permits 7 reissues a week, which is above the
34
+ * 5-duplicate-certificates-per-week limit described above. That is a
35
+ * deliberate choice, not an oversight - reaching it needs a customer to
36
+ * press the button on six consecutive days, and the failure that follows is
37
+ * a clear, temporary error from the CA rather than the sustained burst the
38
+ * per-hour validation limit punishes. The value is a single constant so the
39
+ * trade can be revisited in one place.
40
+ */
41
+ public static readonly COOLDOWN_IN_HOURS: number = 24;
42
+
43
+ /*
44
+ * The newest "requested at" stamp that is already out of cooldown.
45
+ *
46
+ * A row is eligible for another reissue when its stamp is null or is at or
47
+ * before this instant. The server turns this into the WHERE clause it
48
+ * claims the row with, so the comparison that decides eligibility is the
49
+ * same one on both sides.
50
+ */
51
+ public static getCooldownCutoff(now: Date): Date {
52
+ return OneUptimeDate.addRemoveHours(
53
+ OneUptimeDate.fromString(now),
54
+ -CertificateReissueUtil.COOLDOWN_IN_HOURS,
55
+ );
56
+ }
57
+
58
+ // When the domain may be reissued again, given its last request.
59
+ public static getNextReissueAllowedAt(lastRequestedAt: Date): Date {
60
+ return OneUptimeDate.addRemoveHours(
61
+ OneUptimeDate.fromString(lastRequestedAt),
62
+ CertificateReissueUtil.COOLDOWN_IN_HOURS,
63
+ );
64
+ }
65
+
66
+ /*
67
+ * A domain that has never been reissued is never cooling down, which is why
68
+ * null is accepted here rather than being the caller's problem.
69
+ */
70
+ public static isInCooldown(
71
+ lastRequestedAt: Date | null | undefined,
72
+ now: Date,
73
+ ): boolean {
74
+ if (!lastRequestedAt) {
75
+ return false;
76
+ }
77
+
78
+ return OneUptimeDate.isAfter(
79
+ CertificateReissueUtil.getNextReissueAllowedAt(lastRequestedAt),
80
+ OneUptimeDate.fromString(now),
81
+ );
82
+ }
83
+
84
+ /*
85
+ * How much longer the customer has to wait, in words. Whole minutes, since
86
+ * the countdown is only ever read by a person deciding whether to come back
87
+ * later.
88
+ */
89
+ public static getTimeRemainingText(lastRequestedAt: Date, now: Date): string {
90
+ const nextAllowedAt: Date =
91
+ CertificateReissueUtil.getNextReissueAllowedAt(lastRequestedAt);
92
+
93
+ const totalMinutes: number = Math.max(
94
+ 0,
95
+ OneUptimeDate.getMinutesBetweenTwoDates(
96
+ OneUptimeDate.fromString(now),
97
+ nextAllowedAt,
98
+ ),
99
+ );
100
+
101
+ if (totalMinutes < 1) {
102
+ return "less than a minute";
103
+ }
104
+
105
+ const hours: number = Math.floor(totalMinutes / 60);
106
+ const minutes: number = totalMinutes % 60;
107
+
108
+ const parts: Array<string> = [];
109
+
110
+ if (hours > 0) {
111
+ parts.push(`${hours} ${hours === 1 ? "hour" : "hours"}`);
112
+ }
113
+
114
+ if (minutes > 0) {
115
+ parts.push(`${minutes} ${minutes === 1 ? "minute" : "minutes"}`);
116
+ }
117
+
118
+ return parts.join(" ");
119
+ }
120
+
121
+ /*
122
+ * The one sentence the API returns and the dashboard shows. Kept here so a
123
+ * customer reads the same explanation wherever they hit the limit.
124
+ */
125
+ public static getCooldownMessage(lastRequestedAt: Date, now: Date): string {
126
+ return `A certificate reissue was already requested for this domain in the last ${CertificateReissueUtil.COOLDOWN_IN_HOURS} hours. Certificates are issued by Let's Encrypt, which rate limits how often the same domain can be issued, so a reissue can only be requested once every ${CertificateReissueUtil.COOLDOWN_IN_HOURS} hours. Please try again in ${CertificateReissueUtil.getTimeRemainingText(lastRequestedAt, now)}.`;
127
+ }
128
+ }
@@ -0,0 +1,461 @@
1
+ import BadDataException from "../../Types/Exception/BadDataException";
2
+ import GrokPatterns from "./GrokPatterns";
3
+
4
+ /*
5
+ * Grok engine.
6
+ *
7
+ * A grok pattern is a regex with named references into a pattern
8
+ * library: `%{IPV4:client_ip} - %{WORD:verb}` means "the IPv4 regex,
9
+ * captured as client_ip, then a literal ' - ', then a word captured as
10
+ * verb". Anything that is not a `%{...}` reference is passed through to
11
+ * the regex verbatim, so raw regex and grok references can be mixed.
12
+ *
13
+ * Supported reference forms:
14
+ *
15
+ * %{NAME} match, capture nothing
16
+ * %{NAME:field} capture into `field` as a string
17
+ * %{NAME:field:type} capture into `field`, coerced (int/float/boolean)
18
+ *
19
+ * Compilation expands references recursively into one JavaScript RegExp
20
+ * and records, for each captured field, the internal group name that
21
+ * holds it. Only the groups this engine injects capture — every library
22
+ * definition uses `(?:...)` — so extraction is a `match.groups` lookup
23
+ * with no index arithmetic.
24
+ *
25
+ * Matching is deliberately UNANCHORED, like Logstash: a pattern
26
+ * describes a fragment of the line unless the author anchors it with
27
+ * `^`/`$` themselves.
28
+ *
29
+ * This runs once per ingested log record on the telemetry hot path
30
+ * against text the customer's users control, so the compiler enforces
31
+ * hard ceilings on expansion (depth, count, final source length) and
32
+ * the matcher refuses inputs above MAX_GROK_INPUT_LENGTH rather than
33
+ * handing an unbounded string to a backtracking engine.
34
+ */
35
+
36
+ export enum GrokFieldType {
37
+ String = "string",
38
+ Integer = "integer",
39
+ Float = "float",
40
+ Boolean = "boolean",
41
+ }
42
+
43
+ export type GrokValue = string | number | boolean;
44
+
45
+ export interface GrokCapture {
46
+ /** Internal RegExp group name, e.g. "oug0". Never surfaced to users. */
47
+ groupName: string;
48
+ /** Attribute name the user asked for, e.g. "client_ip". */
49
+ fieldName: string;
50
+ fieldType: GrokFieldType;
51
+ }
52
+
53
+ export interface CompiledGrokPattern {
54
+ regex: RegExp;
55
+ captures: Array<GrokCapture>;
56
+ /** Expanded regex source. Useful for debugging and for the UI tester. */
57
+ source: string;
58
+ }
59
+
60
+ /** Longest raw pattern a user may save. */
61
+ export const MAX_GROK_PATTERN_LENGTH: number = 4000;
62
+
63
+ /** Longest expanded regex source a pattern may compile to. */
64
+ export const MAX_GROK_SOURCE_LENGTH: number = 20000;
65
+
66
+ /** How deep `%{A}` -> `%{B}` -> `%{C}` nesting may go. */
67
+ export const MAX_GROK_EXPANSION_DEPTH: number = 20;
68
+
69
+ /** Total number of references expanded while compiling one pattern. */
70
+ export const MAX_GROK_EXPANSIONS: number = 500;
71
+
72
+ /** Fields one pattern may capture. */
73
+ export const MAX_GROK_CAPTURES: number = 100;
74
+
75
+ /*
76
+ * Inputs longer than this are not parsed. A backtracking regex cannot be
77
+ * interrupted once started, so the only bound available on the ingest
78
+ * hot path is the length of what we feed it.
79
+ */
80
+ export const MAX_GROK_INPUT_LENGTH: number = 32768;
81
+
82
+ /*
83
+ * `%{NAME}`, `%{NAME:field}` or `%{NAME:field:type}`. The field and type
84
+ * segments exclude `{`, `}` and `:` so a malformed reference fails to
85
+ * match here and is reported as unparsable rather than being silently
86
+ * split at the wrong colon.
87
+ */
88
+ const GROK_REFERENCE_SOURCE: string =
89
+ "%\\{([A-Za-z0-9_]+)(?::([^:{}]*))?(?::([^:{}]*))?\\}";
90
+
91
+ /*
92
+ * Field names become log attribute keys. Dots are allowed because OTel
93
+ * semantic-convention keys use them (`http.request.method`).
94
+ */
95
+ const FIELD_NAME_REGEX: RegExp = /^[A-Za-z_][A-Za-z0-9_.@-]*$/;
96
+
97
+ interface CompileContext {
98
+ patterns: Record<string, string>;
99
+ captures: Array<GrokCapture>;
100
+ /** Names currently being expanded — used to reject circular references. */
101
+ stack: Array<string>;
102
+ expansions: number;
103
+ }
104
+
105
+ function parseFieldType(rawType: string | undefined): GrokFieldType {
106
+ if (!rawType) {
107
+ return GrokFieldType.String;
108
+ }
109
+
110
+ switch (rawType.trim().toLowerCase()) {
111
+ case "int":
112
+ case "integer":
113
+ case "long":
114
+ return GrokFieldType.Integer;
115
+ case "float":
116
+ case "double":
117
+ case "number":
118
+ return GrokFieldType.Float;
119
+ case "bool":
120
+ case "boolean":
121
+ return GrokFieldType.Boolean;
122
+ case "string":
123
+ case "text":
124
+ return GrokFieldType.String;
125
+ default:
126
+ throw new BadDataException(
127
+ `Unknown grok field type "${rawType}". Supported types are: int, long, float, double, boolean, string.`,
128
+ );
129
+ }
130
+ }
131
+
132
+ function resolveReference(
133
+ match: RegExpExecArray,
134
+ context: CompileContext,
135
+ ): string {
136
+ const patternName: string = match[1] as string;
137
+ const rawFieldName: string | undefined = match[2];
138
+ const rawFieldType: string | undefined = match[3];
139
+
140
+ context.expansions++;
141
+
142
+ if (context.expansions > MAX_GROK_EXPANSIONS) {
143
+ throw new BadDataException(
144
+ `This grok pattern expands to more than ${MAX_GROK_EXPANSIONS} sub-patterns. Please simplify it.`,
145
+ );
146
+ }
147
+
148
+ const definition: string | undefined = context.patterns[patternName];
149
+
150
+ if (definition === undefined) {
151
+ throw new BadDataException(
152
+ `Unknown grok pattern "%{${patternName}}". Check the list of supported patterns.`,
153
+ );
154
+ }
155
+
156
+ if (context.stack.includes(patternName)) {
157
+ throw new BadDataException(
158
+ `Grok pattern "%{${patternName}}" refers to itself. Circular pattern references are not supported.`,
159
+ );
160
+ }
161
+
162
+ if (context.stack.length >= MAX_GROK_EXPANSION_DEPTH) {
163
+ throw new BadDataException(
164
+ `Grok pattern "%{${patternName}}" nests more than ${MAX_GROK_EXPANSION_DEPTH} levels deep. Please simplify it.`,
165
+ );
166
+ }
167
+
168
+ context.stack.push(patternName);
169
+ const expanded: string = expandPattern(definition, context);
170
+ context.stack.pop();
171
+
172
+ if (rawFieldName === undefined) {
173
+ return `(?:${expanded})`;
174
+ }
175
+
176
+ const fieldName: string = rawFieldName.trim();
177
+
178
+ if (!FIELD_NAME_REGEX.test(fieldName)) {
179
+ throw new BadDataException(
180
+ `"${rawFieldName}" is not a valid grok field name. Use letters, digits, and . _ - @ (starting with a letter or underscore).`,
181
+ );
182
+ }
183
+
184
+ if (context.captures.length >= MAX_GROK_CAPTURES) {
185
+ throw new BadDataException(
186
+ `This grok pattern captures more than ${MAX_GROK_CAPTURES} fields. Please capture fewer fields.`,
187
+ );
188
+ }
189
+
190
+ const groupName: string = `oug${context.captures.length}`;
191
+
192
+ context.captures.push({
193
+ groupName: groupName,
194
+ fieldName: fieldName,
195
+ fieldType: parseFieldType(rawFieldType),
196
+ });
197
+
198
+ return `(?<${groupName}>${expanded})`;
199
+ }
200
+
201
+ function expandPattern(source: string, context: CompileContext): string {
202
+ /*
203
+ * A fresh RegExp per call: `lastIndex` is per-object state and
204
+ * expansion recurses, so a shared instance would have nested calls
205
+ * stepping on each other's scan position.
206
+ */
207
+ const referenceRegex: RegExp = new RegExp(GROK_REFERENCE_SOURCE, "g");
208
+
209
+ let output: string = "";
210
+ let cursor: number = 0;
211
+ let match: RegExpExecArray | null = referenceRegex.exec(source);
212
+
213
+ while (match !== null) {
214
+ output += source.slice(cursor, match.index);
215
+ output += resolveReference(match, context);
216
+ cursor = match.index + match[0].length;
217
+
218
+ if (output.length > MAX_GROK_SOURCE_LENGTH) {
219
+ throw new BadDataException(
220
+ `This grok pattern expands to more than ${MAX_GROK_SOURCE_LENGTH} characters of regex. Please simplify it.`,
221
+ );
222
+ }
223
+
224
+ match = referenceRegex.exec(source);
225
+ }
226
+
227
+ output += source.slice(cursor);
228
+
229
+ return output;
230
+ }
231
+
232
+ /*
233
+ * Compile a grok pattern. Throws BadDataException with a message meant
234
+ * for the person who typed the pattern — this is what save-time
235
+ * validation and the pattern tester in the dashboard show.
236
+ */
237
+ export function compileGrokPattern(
238
+ pattern: string,
239
+ extraPatterns?: Record<string, string> | undefined,
240
+ ): CompiledGrokPattern {
241
+ if (typeof pattern !== "string" || pattern.trim().length === 0) {
242
+ throw new BadDataException("Grok pattern cannot be empty.");
243
+ }
244
+
245
+ if (pattern.length > MAX_GROK_PATTERN_LENGTH) {
246
+ throw new BadDataException(
247
+ `Grok pattern cannot be longer than ${MAX_GROK_PATTERN_LENGTH} characters.`,
248
+ );
249
+ }
250
+
251
+ const context: CompileContext = {
252
+ patterns: extraPatterns
253
+ ? { ...GrokPatterns, ...extraPatterns }
254
+ : GrokPatterns,
255
+ captures: [],
256
+ stack: [],
257
+ expansions: 0,
258
+ };
259
+
260
+ const source: string = expandPattern(pattern, context);
261
+
262
+ if (source.length > MAX_GROK_SOURCE_LENGTH) {
263
+ throw new BadDataException(
264
+ `This grok pattern expands to more than ${MAX_GROK_SOURCE_LENGTH} characters of regex. Please simplify it.`,
265
+ );
266
+ }
267
+
268
+ let regex: RegExp;
269
+
270
+ try {
271
+ /*
272
+ * No `g`/`y` flag on purpose: those carry `lastIndex` between calls
273
+ * and a compiled pattern is reused for every record.
274
+ */
275
+ regex = new RegExp(source);
276
+ } catch (err) {
277
+ throw new BadDataException(
278
+ `This grok pattern is not valid: ${err instanceof Error ? err.message : String(err)}`,
279
+ );
280
+ }
281
+
282
+ return {
283
+ regex: regex,
284
+ captures: context.captures,
285
+ source: source,
286
+ };
287
+ }
288
+
289
+ function coerceValue(raw: string, fieldType: GrokFieldType): GrokValue {
290
+ if (fieldType === GrokFieldType.Integer) {
291
+ const parsed: number = parseInt(raw, 10);
292
+ return Number.isFinite(parsed) ? parsed : raw;
293
+ }
294
+
295
+ if (fieldType === GrokFieldType.Float) {
296
+ const parsed: number = parseFloat(raw);
297
+ return Number.isFinite(parsed) ? parsed : raw;
298
+ }
299
+
300
+ if (fieldType === GrokFieldType.Boolean) {
301
+ const normalized: string = raw.trim().toLowerCase();
302
+
303
+ if (
304
+ normalized === "true" ||
305
+ normalized === "yes" ||
306
+ normalized === "y" ||
307
+ normalized === "1"
308
+ ) {
309
+ return true;
310
+ }
311
+
312
+ if (
313
+ normalized === "false" ||
314
+ normalized === "no" ||
315
+ normalized === "n" ||
316
+ normalized === "0"
317
+ ) {
318
+ return false;
319
+ }
320
+
321
+ /*
322
+ * Not recognisably a boolean — keep the raw text rather than
323
+ * inventing a `false` the log never said.
324
+ */
325
+ return raw;
326
+ }
327
+
328
+ return raw;
329
+ }
330
+
331
+ /*
332
+ * Run a compiled pattern against one string. Returns null when the
333
+ * pattern does not match; returns the captured fields otherwise (which
334
+ * is an empty object for a pattern that matches but captures nothing).
335
+ *
336
+ * Empty captures are dropped, matching Logstash's default
337
+ * `keep_empty_captures => false`: an optional group that did not
338
+ * participate should not write a blank attribute onto the log.
339
+ */
340
+ export function matchGrokPattern(
341
+ compiled: CompiledGrokPattern,
342
+ input: string,
343
+ ): Record<string, GrokValue> | null {
344
+ if (typeof input !== "string" || input.length === 0) {
345
+ return null;
346
+ }
347
+
348
+ if (input.length > MAX_GROK_INPUT_LENGTH) {
349
+ return null;
350
+ }
351
+
352
+ const match: RegExpExecArray | null = compiled.regex.exec(input);
353
+
354
+ if (!match) {
355
+ return null;
356
+ }
357
+
358
+ const groups: Record<string, string | undefined> = match.groups || {};
359
+ const extracted: Record<string, GrokValue> = {};
360
+
361
+ for (const capture of compiled.captures) {
362
+ const raw: string | undefined = groups[capture.groupName];
363
+
364
+ if (raw === undefined || raw === "") {
365
+ continue;
366
+ }
367
+
368
+ /*
369
+ * The same field name can legitimately appear twice (alternation
370
+ * branches, or a library pattern that already names it). Whichever
371
+ * group actually matched first wins, so a later branch that did not
372
+ * participate cannot blank out a real value.
373
+ */
374
+ if (extracted[capture.fieldName] !== undefined) {
375
+ continue;
376
+ }
377
+
378
+ extracted[capture.fieldName] = coerceValue(raw, capture.fieldType);
379
+ }
380
+
381
+ return extracted;
382
+ }
383
+
384
+ /*
385
+ * Process-wide compile cache for the ingest path.
386
+ *
387
+ * Compiling walks the pattern library and builds a RegExp; doing that
388
+ * per log record would dominate the cost of the processor. Compiled
389
+ * patterns are immutable and carry no `lastIndex` state (no `g` flag),
390
+ * so one instance is safely shared by every project using the same
391
+ * pattern text.
392
+ *
393
+ * Failures are cached too. An invalid pattern that reaches ingest would
394
+ * otherwise be recompiled — and rejected — once per record.
395
+ */
396
+ const compileCache: Map<string, CompiledGrokPattern | BadDataException> =
397
+ new Map<string, CompiledGrokPattern | BadDataException>();
398
+
399
+ export const MAX_CACHED_GROK_PATTERNS: number = 500;
400
+
401
+ export function compileGrokPatternCached(pattern: string): CompiledGrokPattern {
402
+ const cached: CompiledGrokPattern | BadDataException | undefined =
403
+ compileCache.get(pattern);
404
+
405
+ if (cached !== undefined) {
406
+ if (cached instanceof BadDataException) {
407
+ throw cached;
408
+ }
409
+
410
+ return cached;
411
+ }
412
+
413
+ let result: CompiledGrokPattern | BadDataException;
414
+
415
+ try {
416
+ result = compileGrokPattern(pattern);
417
+ } catch (err) {
418
+ result =
419
+ err instanceof BadDataException ? err : new BadDataException(String(err));
420
+ }
421
+
422
+ if (compileCache.size >= MAX_CACHED_GROK_PATTERNS) {
423
+ // Insertion-ordered: drop the oldest entry to bound the cache.
424
+ const oldestKey: string | undefined = compileCache.keys().next().value;
425
+
426
+ if (oldestKey !== undefined) {
427
+ compileCache.delete(oldestKey);
428
+ }
429
+ }
430
+
431
+ compileCache.set(pattern, result);
432
+
433
+ if (result instanceof BadDataException) {
434
+ throw result;
435
+ }
436
+
437
+ return result;
438
+ }
439
+
440
+ /** Test seam: forget every cached compilation. */
441
+ export function clearGrokCompileCache(): void {
442
+ compileCache.clear();
443
+ }
444
+
445
+ /*
446
+ * Compile + match in one call. Convenience for the dashboard's pattern
447
+ * tester and for tests; ingest compiles once and reuses the result.
448
+ */
449
+ export function parseWithGrokPattern(
450
+ pattern: string,
451
+ input: string,
452
+ ): Record<string, GrokValue> | null {
453
+ return matchGrokPattern(compileGrokPattern(pattern), input);
454
+ }
455
+
456
+ export default {
457
+ compileGrokPattern,
458
+ compileGrokPatternCached,
459
+ matchGrokPattern,
460
+ parseWithGrokPattern,
461
+ };