@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.
- package/Models/DatabaseModels/DashboardDomain.ts +43 -0
- package/Models/DatabaseModels/Index.ts +11 -0
- package/Models/DatabaseModels/MonitorTemplate.ts +15 -3
- package/Models/DatabaseModels/OnCallDutyPolicySchedule.ts +43 -0
- package/Models/DatabaseModels/OnCallDutyPolicyScheduleCalendarFeed.ts +662 -0
- package/Models/DatabaseModels/ProjectOnCallCalendarFeed.ts +584 -0
- package/Models/DatabaseModels/StatusPageDomain.ts +43 -0
- package/Models/DatabaseModels/UserOnCallCalendarFeed.ts +546 -0
- package/Models/DatabaseModels/UserOnCallShiftReminder.ts +231 -0
- package/Models/DatabaseModels/UserOnCallShiftReminderLog.ts +331 -0
- package/Server/API/DashboardDomainAPI.ts +74 -0
- package/Server/API/MicrosoftTeamsAPI.ts +81 -180
- package/Server/API/OnCallCalendarAPI.ts +2194 -0
- package/Server/API/StatusPageDomainAPI.ts +74 -0
- package/Server/EnvironmentConfig.ts +138 -0
- package/Server/Infrastructure/OnCallCalendarFeedCache.ts +1050 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1790200000000-AllowNullMonitorNameOnMonitorTemplate.ts +43 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1790300000000-AddCertificateReissueRequestedAtToDomains.ts +40 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1790400000000-AddOnCallCalendarFeeds.ts +253 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +6 -0
- package/Server/Middleware/OnCallCalendarFeedRateLimit.ts +487 -0
- package/Server/Middleware/ProjectAuthorization.ts +6 -1
- package/Server/Services/DashboardDomainService.ts +131 -0
- package/Server/Services/Index.ts +12 -0
- package/Server/Services/LogPipelineProcessorService.ts +88 -0
- package/Server/Services/MonitorTemplateService.ts +70 -11
- package/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.ts +32 -0
- package/Server/Services/OnCallDutyPolicyScheduleCalendarFeedService.ts +260 -0
- package/Server/Services/OnCallDutyPolicyScheduleLayerService.ts +70 -3
- package/Server/Services/OnCallDutyPolicyScheduleLayerUserService.ts +138 -3
- package/Server/Services/OnCallDutyPolicyScheduleService.ts +1465 -134
- package/Server/Services/OnCallDutyPolicyUserOverrideService.ts +167 -31
- package/Server/Services/ProjectOnCallCalendarFeedService.ts +192 -0
- package/Server/Services/StatusPageDomainService.ts +163 -3
- package/Server/Services/StatusPagePrivateUserSessionService.ts +197 -56
- package/Server/Services/TeamMemberService.ts +489 -1
- package/Server/Services/TeamService.ts +50 -0
- package/Server/Services/UserNotificationSettingService.ts +44 -1
- package/Server/Services/UserOnCallCalendarFeedService.ts +159 -0
- package/Server/Services/UserOnCallShiftReminderLogService.ts +151 -0
- package/Server/Services/UserOnCallShiftReminderService.ts +112 -0
- package/Server/Types/Domain.ts +17 -0
- package/Server/Utils/APIKey/AccessPermission.ts +24 -0
- package/Server/Utils/Greenlock/Greenlock.ts +156 -58
- package/Server/Utils/LogPipelineProcessorValidation.ts +112 -0
- package/Server/Utils/OnCall/CalendarFeedToken.ts +241 -0
- package/Server/Utils/OnCall/OnCallCalendarFeedRenderer.ts +1488 -0
- package/Server/Utils/OnCall/OnCallCalendarFeedUrls.ts +230 -0
- package/Server/Utils/OnCall/OnCallShiftChangeListeners.ts +227 -0
- package/Server/Utils/OnCall/OnCallShiftMaterializer.ts +1127 -0
- package/Server/Utils/OnCall/OnCallShiftReminderListener.ts +174 -0
- package/Server/Utils/OnCall/OnCallShiftReminderRunner.ts +2584 -0
- package/Server/Utils/Response.ts +134 -0
- package/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsClient.ts +1094 -45
- package/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsPoller.ts +153 -17
- package/Server/Utils/StartServer.ts +10 -0
- package/Server/Utils/Telemetry/AppMetrics.ts +51 -0
- package/Server/Utils/Workspace/MicrosoftTeams/Actions/Alert.ts +23 -11
- package/Server/Utils/Workspace/MicrosoftTeams/Actions/Auth.ts +0 -170
- package/Server/Utils/Workspace/MicrosoftTeams/Actions/Authorization.ts +158 -0
- package/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.ts +23 -11
- package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.ts +35 -13
- package/Tests/App/Dashboard/MonitorTemplateColumnAndFacet.test.tsx +505 -0
- package/Tests/App/Dashboard/OnCallCalendarFeedLinks.test.tsx +229 -0
- package/Tests/App/Dashboard/OnCallCalendarFeedPlanGate.test.tsx +489 -0
- package/Tests/App/Dashboard/OnCallCalendarFeedSideMenus.test.tsx +149 -0
- package/Tests/App/Dashboard/OnCallCalendarFeedUtil.test.ts +855 -0
- package/Tests/App/Dashboard/OnCallPersonalCalendarFeed.test.tsx +1209 -0
- package/Tests/App/Dashboard/OnCallSharedCalendarFeedCard.test.tsx +1019 -0
- package/Tests/App/Dashboard/OnCallShiftRemindersAndUpcomingShifts.test.tsx +655 -0
- package/Tests/App/Dashboard/UserSettingsSetupChecklistModel.test.ts +73 -0
- package/Tests/App/StatusPage/StatusPageLoginCodeBootstrap.test.ts +106 -0
- package/Tests/App/StatusPage/StatusPageLoginCodeUtil.test.ts +84 -0
- package/Tests/App/StatusPage/StatusPageRedirectSafety.test.ts +119 -0
- package/Tests/Models/MonitorTemplateMonitorNameColumn.test.ts +258 -0
- package/Tests/Models/OnCallCalendarFeedModels.test.ts +642 -0
- package/Tests/Models/OnCallDutyPolicyScheduleCalendarFeed.test.ts +288 -0
- package/Tests/Models/OnCallDutyPolicyScheduleShiftConfigVersion.test.ts +88 -0
- package/Tests/Models/UserOnCallShiftReminderModels.test.ts +368 -0
- package/Tests/Server/API/CustomDomainReissueSslAPI.test.ts +469 -0
- package/Tests/Server/API/Helpers.ts +8 -0
- package/Tests/Server/API/MicrosoftTeamsBotMessagesEndpoint.test.ts +729 -0
- package/Tests/Server/API/MicrosoftTeamsBotTestEndpoint.test.ts +26 -0
- package/Tests/Server/API/MicrosoftTeamsLegacyWebhookRemoval.test.ts +402 -0
- package/Tests/Server/API/OnCallCalendarAPI.test.ts +4461 -0
- package/Tests/Server/EnvironmentConfigOnCallCalendarFeed.test.ts +357 -0
- package/Tests/Server/Infrastructure/OnCallCalendarFeedCache.test.ts +1589 -0
- package/Tests/Server/Infrastructure/Postgres/AddOnCallCalendarFeedsMigration.test.ts +369 -0
- package/Tests/Server/Middleware/OnCallCalendarFeedRateLimit.test.ts +1365 -0
- package/Tests/Server/Middleware/ProjectAuthorizationApiKeyMiddleware.test.ts +4 -0
- package/Tests/Server/Services/AddCertificateReissueRequestedAtToDomainsMigration.test.ts +287 -0
- package/Tests/Server/Services/CustomDomainCertificateReissue.test.ts +477 -0
- package/Tests/Server/Services/FeedRetentionConsistency.test.ts +70 -0
- package/Tests/Server/Services/LogPipelineProcessorSaveValidation.test.ts +249 -0
- package/Tests/Server/Services/MonitorTemplateServiceBulkSync.test.ts +549 -0
- package/Tests/Server/Services/MonitorTemplateServiceNetworkDeviceSync.test.ts +16 -3
- package/Tests/Server/Services/NetworkDeviceAutoImportRuleEngineService.test.ts +57 -0
- package/Tests/Server/Services/OnCallCalendarFeedServices.test.ts +1103 -0
- package/Tests/Server/Services/OnCallDutyPolicyScheduleResolver.test.ts +1037 -0
- package/Tests/Server/Services/OnCallShiftConfigPropagation.test.ts +1270 -0
- package/Tests/Server/Services/SecurityEventLastErrorColumnWidth.test.ts +151 -15
- package/Tests/Server/Services/StatusPagePrivateUserSessionService.test.ts +587 -0
- package/Tests/Server/Services/TeamDeleteMemberCleanup.test.ts +156 -0
- package/Tests/Server/Services/TeamMemberOnCallCleanup.test.ts +755 -0
- package/Tests/Server/Services/UserNotificationSettingShiftReminderDefaults.test.ts +267 -0
- package/Tests/Server/Services/UserOnCallShiftReminderServices.test.ts +583 -0
- package/Tests/Server/Types/Database/Permissions/ApiKeyFileAccess.test.ts +286 -0
- package/Tests/Server/Types/Database/Permissions/MonitorTemplateColumnAccess.test.ts +328 -0
- package/Tests/Server/Types/Database/Permissions/OnCallCalendarFeedPermissions.test.ts +254 -0
- package/Tests/Server/Types/Database/QueryHelperFindWithSameTextAndIsNull.test.ts +83 -0
- package/Tests/Server/Utils/AI/SRE/ConfidenceSignal.test.ts +377 -0
- package/Tests/Server/Utils/APIKey/AccessPermission.test.ts +16 -1
- package/Tests/Server/Utils/Greenlock/CertificateRenewalSchedule.test.ts +250 -0
- package/Tests/Server/Utils/LogPipelineProcessorValidation.test.ts +198 -0
- package/Tests/Server/Utils/OnCall/CalendarFeedToken.test.ts +467 -0
- package/Tests/Server/Utils/OnCall/OnCallCalendarFeedRenderer.test.ts +2142 -0
- package/Tests/Server/Utils/OnCall/OnCallCalendarFeedUrls.test.ts +278 -0
- package/Tests/Server/Utils/OnCall/OnCallResolverTestHarness.ts +440 -0
- package/Tests/Server/Utils/OnCall/OnCallShiftChangeListeners.test.ts +314 -0
- package/Tests/Server/Utils/OnCall/OnCallShiftMaterializer.test.ts +1502 -0
- package/Tests/Server/Utils/OnCall/OnCallShiftReminderListener.test.ts +491 -0
- package/Tests/Server/Utils/OnCall/OnCallShiftReminderRunner.test.ts +3088 -0
- package/Tests/Server/Utils/OnCall/OnCallShiftReminderTestHarness.ts +910 -0
- package/Tests/Server/Utils/ResponseSendCalendarResponse.test.ts +561 -0
- package/Tests/Server/Utils/SecurityEvent/ConnectorErrorMessage.test.ts +48 -9
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsAuth.test.ts +726 -0
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsClient.test.ts +74 -11
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsErrorHandling.test.ts +1107 -0
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsPoller.test.ts +20 -3
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsPollerFailureTaxonomy.test.ts +51 -11
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsPollerHardening.test.ts +1246 -0
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsRequestContract.test.ts +961 -0
- package/Tests/Server/Utils/SecurityEvent/GoogleSecOpsResponseParsing.test.ts +653 -0
- package/Tests/Server/Utils/StartServerEncryptionSecretWarning.test.ts +64 -0
- package/Tests/Server/Utils/Telemetry/AppMetrics.test.ts +29 -0
- package/Tests/Server/Utils/Workspace/MicrosoftTeamsActionAuthorization.test.ts +880 -0
- package/Tests/Types/API/HTTPResponse.test.ts +175 -0
- package/Tests/Types/API/Route.test.ts +36 -4
- package/Tests/Types/Calendar/ICalendar.test.ts +488 -0
- package/Tests/Types/Database/DatabaseProperty.test.ts +171 -0
- package/Tests/Types/DateLocalShortDateTimeString.test.ts +518 -0
- package/Tests/Types/DateLocalTimeString.test.ts +259 -0
- package/Tests/Types/DateUserPrefers12HourFormat.test.ts +316 -0
- package/Tests/Types/NotificationSetting/NotificationSettingEventType.test.ts +53 -0
- package/Tests/Types/OnCallDutyPolicy/CalendarFeedTestFixtures.ts +310 -0
- package/Tests/Types/OnCallDutyPolicy/CalendarFeedWindow.test.ts +205 -0
- package/Tests/Types/OnCallDutyPolicy/LayerUtilLayerMetaAndIterationCap.test.ts +458 -0
- package/Tests/Types/OnCallDutyPolicy/MaterializedShift.test.ts +197 -0
- package/Tests/Types/OnCallDutyPolicy/OnCallCalendarFeedUtil.test.ts +1986 -0
- package/Tests/Types/OnCallDutyPolicy/ScheduleShiftUtilGroupKey.test.ts +678 -0
- package/Tests/Types/OnCallDutyPolicy/ShiftSeamUtil.test.ts +417 -0
- package/Tests/UI/Components/LogsHistogram.test.tsx +41 -2
- package/Tests/UI/Components/LogsViewerEmptyStateTimeRange.test.tsx +212 -0
- package/Tests/UI/Components/TelemetryChartClockFormat.test.tsx +359 -0
- package/Tests/UI/Components/TimeRangePickerClockFormat.test.tsx +422 -0
- package/Tests/UI/Components/TimeRangePickerDropdown.test.tsx +146 -8
- package/Tests/UI/MicrosoftTeams/MicrosoftTeamsMessagingEndpointGuidance.test.tsx +520 -0
- package/Tests/UI/Utils/Breadcrumb/fixtures/RealBreadcrumbTrails.ts +10 -0
- package/Tests/UI/Utils/Breadcrumb/fixtures/RealRoutePatterns.ts +2 -0
- package/Tests/UI/Utils/Navigation.test.ts +82 -0
- package/Tests/Utils/Array.test.ts +100 -0
- package/Tests/Utils/CertificateReissue.test.ts +225 -0
- package/Tests/Utils/Grok/Grok.test.ts +492 -0
- package/Tests/Utils/Monitor/NetworkDeviceMonitorTemplateUtil.test.ts +181 -13
- package/Types/API/Route.ts +20 -5
- package/Types/Calendar/ICalendar.ts +442 -0
- package/Types/Date.ts +143 -13
- package/Types/Email/EmailTemplateType.ts +2 -0
- package/Types/NotificationSetting/NotificationSettingEventType.ts +4 -0
- package/Types/OnCallDutyPolicy/CalendarFeedWindow.ts +140 -0
- package/Types/OnCallDutyPolicy/Layer.ts +190 -35
- package/Types/OnCallDutyPolicy/MaterializedShift.ts +274 -0
- package/Types/OnCallDutyPolicy/OnCallCalendarFeedUtil.ts +1415 -0
- package/Types/OnCallDutyPolicy/ScheduleShiftUtil.ts +159 -4
- package/Types/OnCallDutyPolicy/ShiftSeamUtil.ts +106 -0
- package/Types/Rum/SessionReplay.ts +62 -1
- package/UI/Components/Date/TimeRangePickerDropdown.tsx +9 -5
- package/UI/Components/LogsViewer/LogsViewer.tsx +12 -7
- package/UI/Components/LogsViewer/components/HistogramTooltip.tsx +18 -17
- package/UI/Components/LogsViewer/components/LogsAnalyticsView.tsx +21 -28
- package/UI/Components/LogsViewer/components/LogsHistogram.tsx +2 -4
- package/UI/Components/TelemetryViewer/components/TelemetryHistogram.tsx +2 -4
- package/UI/Components/TelemetryViewer/components/TelemetryHistogramTooltip.tsx +17 -16
- package/UI/Utils/Navigation.ts +42 -0
- package/Utils/Array.ts +37 -0
- package/Utils/CertificateReissue.ts +128 -0
- package/Utils/Grok/Grok.ts +461 -0
- package/Utils/Grok/GrokPatterns.ts +118 -0
- package/Utils/Monitor/NetworkDeviceMonitorTemplateUtil.ts +58 -6
- package/build/dist/Models/DatabaseModels/DashboardDomain.js +44 -0
- package/build/dist/Models/DatabaseModels/DashboardDomain.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Index.js +11 -0
- package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/MonitorTemplate.js +17 -4
- package/build/dist/Models/DatabaseModels/MonitorTemplate.js.map +1 -1
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicySchedule.js +44 -0
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicySchedule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyScheduleCalendarFeed.js +699 -0
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyScheduleCalendarFeed.js.map +1 -0
- package/build/dist/Models/DatabaseModels/ProjectOnCallCalendarFeed.js +620 -0
- package/build/dist/Models/DatabaseModels/ProjectOnCallCalendarFeed.js.map +1 -0
- package/build/dist/Models/DatabaseModels/StatusPageDomain.js +44 -0
- package/build/dist/Models/DatabaseModels/StatusPageDomain.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserOnCallCalendarFeed.js +585 -0
- package/build/dist/Models/DatabaseModels/UserOnCallCalendarFeed.js.map +1 -0
- package/build/dist/Models/DatabaseModels/UserOnCallShiftReminder.js +247 -0
- package/build/dist/Models/DatabaseModels/UserOnCallShiftReminder.js.map +1 -0
- package/build/dist/Models/DatabaseModels/UserOnCallShiftReminderLog.js +355 -0
- package/build/dist/Models/DatabaseModels/UserOnCallShiftReminderLog.js.map +1 -0
- package/build/dist/Server/API/DashboardDomainAPI.js +43 -1
- package/build/dist/Server/API/DashboardDomainAPI.js.map +1 -1
- package/build/dist/Server/API/MicrosoftTeamsAPI.js +74 -118
- package/build/dist/Server/API/MicrosoftTeamsAPI.js.map +1 -1
- package/build/dist/Server/API/OnCallCalendarAPI.js +1371 -0
- package/build/dist/Server/API/OnCallCalendarAPI.js.map +1 -0
- package/build/dist/Server/API/StatusPageDomainAPI.js +43 -1
- package/build/dist/Server/API/StatusPageDomainAPI.js.map +1 -1
- package/build/dist/Server/EnvironmentConfig.js +102 -0
- package/build/dist/Server/EnvironmentConfig.js.map +1 -1
- package/build/dist/Server/Infrastructure/OnCallCalendarFeedCache.js +663 -0
- package/build/dist/Server/Infrastructure/OnCallCalendarFeedCache.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790200000000-AllowNullMonitorNameOnMonitorTemplate.js +34 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790200000000-AllowNullMonitorNameOnMonitorTemplate.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790300000000-AddCertificateReissueRequestedAtToDomains.js +28 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790300000000-AddCertificateReissueRequestedAtToDomains.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790400000000-AddOnCallCalendarFeeds.js +103 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1790400000000-AddOnCallCalendarFeeds.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +6 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Middleware/OnCallCalendarFeedRateLimit.js +342 -0
- package/build/dist/Server/Middleware/OnCallCalendarFeedRateLimit.js.map +1 -0
- package/build/dist/Server/Middleware/ProjectAuthorization.js +6 -1
- package/build/dist/Server/Middleware/ProjectAuthorization.js.map +1 -1
- package/build/dist/Server/Services/DashboardDomainService.js +104 -0
- package/build/dist/Server/Services/DashboardDomainService.js.map +1 -1
- package/build/dist/Server/Services/Index.js +12 -0
- package/build/dist/Server/Services/Index.js.map +1 -1
- package/build/dist/Server/Services/LogPipelineProcessorService.js +65 -0
- package/build/dist/Server/Services/LogPipelineProcessorService.js.map +1 -1
- package/build/dist/Server/Services/MonitorTemplateService.js +57 -11
- package/build/dist/Server/Services/MonitorTemplateService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js +20 -0
- package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyScheduleCalendarFeedService.js +219 -0
- package/build/dist/Server/Services/OnCallDutyPolicyScheduleCalendarFeedService.js.map +1 -0
- package/build/dist/Server/Services/OnCallDutyPolicyScheduleLayerService.js +47 -3
- package/build/dist/Server/Services/OnCallDutyPolicyScheduleLayerService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyScheduleLayerUserService.js +112 -3
- package/build/dist/Server/Services/OnCallDutyPolicyScheduleLayerUserService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyScheduleService.js +955 -9
- package/build/dist/Server/Services/OnCallDutyPolicyScheduleService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyUserOverrideService.js +93 -6
- package/build/dist/Server/Services/OnCallDutyPolicyUserOverrideService.js.map +1 -1
- package/build/dist/Server/Services/ProjectOnCallCalendarFeedService.js +157 -0
- package/build/dist/Server/Services/ProjectOnCallCalendarFeedService.js.map +1 -0
- package/build/dist/Server/Services/StatusPageDomainService.js +132 -3
- package/build/dist/Server/Services/StatusPageDomainService.js.map +1 -1
- package/build/dist/Server/Services/StatusPagePrivateUserSessionService.js +112 -32
- package/build/dist/Server/Services/StatusPagePrivateUserSessionService.js.map +1 -1
- package/build/dist/Server/Services/TeamMemberService.js +396 -1
- package/build/dist/Server/Services/TeamMemberService.js.map +1 -1
- package/build/dist/Server/Services/TeamService.js +43 -0
- package/build/dist/Server/Services/TeamService.js.map +1 -1
- package/build/dist/Server/Services/UserNotificationSettingService.js +26 -1
- package/build/dist/Server/Services/UserNotificationSettingService.js.map +1 -1
- package/build/dist/Server/Services/UserOnCallCalendarFeedService.js +140 -0
- package/build/dist/Server/Services/UserOnCallCalendarFeedService.js.map +1 -0
- package/build/dist/Server/Services/UserOnCallShiftReminderLogService.js +116 -0
- package/build/dist/Server/Services/UserOnCallShiftReminderLogService.js.map +1 -0
- package/build/dist/Server/Services/UserOnCallShiftReminderService.js +92 -0
- package/build/dist/Server/Services/UserOnCallShiftReminderService.js.map +1 -0
- package/build/dist/Server/Types/Domain.js +16 -0
- package/build/dist/Server/Types/Domain.js.map +1 -1
- package/build/dist/Server/Utils/APIKey/AccessPermission.js +24 -0
- package/build/dist/Server/Utils/APIKey/AccessPermission.js.map +1 -1
- package/build/dist/Server/Utils/Greenlock/Greenlock.js +110 -35
- package/build/dist/Server/Utils/Greenlock/Greenlock.js.map +1 -1
- package/build/dist/Server/Utils/LogPipelineProcessorValidation.js +77 -0
- package/build/dist/Server/Utils/LogPipelineProcessorValidation.js.map +1 -0
- package/build/dist/Server/Utils/OnCall/CalendarFeedToken.js +161 -0
- package/build/dist/Server/Utils/OnCall/CalendarFeedToken.js.map +1 -0
- package/build/dist/Server/Utils/OnCall/OnCallCalendarFeedRenderer.js +983 -0
- package/build/dist/Server/Utils/OnCall/OnCallCalendarFeedRenderer.js.map +1 -0
- package/build/dist/Server/Utils/OnCall/OnCallCalendarFeedUrls.js +155 -0
- package/build/dist/Server/Utils/OnCall/OnCallCalendarFeedUrls.js.map +1 -0
- package/build/dist/Server/Utils/OnCall/OnCallShiftChangeListeners.js +145 -0
- package/build/dist/Server/Utils/OnCall/OnCallShiftChangeListeners.js.map +1 -0
- package/build/dist/Server/Utils/OnCall/OnCallShiftMaterializer.js +752 -0
- package/build/dist/Server/Utils/OnCall/OnCallShiftMaterializer.js.map +1 -0
- package/build/dist/Server/Utils/OnCall/OnCallShiftReminderListener.js +92 -0
- package/build/dist/Server/Utils/OnCall/OnCallShiftReminderListener.js.map +1 -0
- package/build/dist/Server/Utils/OnCall/OnCallShiftReminderRunner.js +1786 -0
- package/build/dist/Server/Utils/OnCall/OnCallShiftReminderRunner.js.map +1 -0
- package/build/dist/Server/Utils/Response.js +97 -0
- package/build/dist/Server/Utils/Response.js.map +1 -1
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsClient.js +777 -36
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsClient.js.map +1 -1
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsPoller.js +108 -17
- package/build/dist/Server/Utils/SecurityEvent/GoogleSecOps/GoogleSecOpsPoller.js.map +1 -1
- package/build/dist/Server/Utils/StartServer.js +9 -1
- package/build/dist/Server/Utils/StartServer.js.map +1 -1
- package/build/dist/Server/Utils/Telemetry/AppMetrics.js +41 -0
- package/build/dist/Server/Utils/Telemetry/AppMetrics.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Alert.js +17 -6
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Alert.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Auth.js +0 -159
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Auth.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Authorization.js +128 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Authorization.js.map +1 -0
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.js +17 -6
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Actions/Incident.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js +25 -13
- package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js.map +1 -1
- package/build/dist/Types/API/Route.js +16 -5
- package/build/dist/Types/API/Route.js.map +1 -1
- package/build/dist/Types/Calendar/ICalendar.js +290 -0
- package/build/dist/Types/Calendar/ICalendar.js.map +1 -0
- package/build/dist/Types/Date.js +115 -13
- package/build/dist/Types/Date.js.map +1 -1
- package/build/dist/Types/Email/EmailTemplateType.js +2 -0
- package/build/dist/Types/Email/EmailTemplateType.js.map +1 -1
- package/build/dist/Types/NotificationSetting/NotificationSettingEventType.js +3 -0
- package/build/dist/Types/NotificationSetting/NotificationSettingEventType.js.map +1 -1
- package/build/dist/Types/OnCallDutyPolicy/CalendarFeedWindow.js +97 -0
- package/build/dist/Types/OnCallDutyPolicy/CalendarFeedWindow.js.map +1 -0
- package/build/dist/Types/OnCallDutyPolicy/Layer.js +113 -19
- package/build/dist/Types/OnCallDutyPolicy/Layer.js.map +1 -1
- package/build/dist/Types/OnCallDutyPolicy/MaterializedShift.js +134 -0
- package/build/dist/Types/OnCallDutyPolicy/MaterializedShift.js.map +1 -0
- package/build/dist/Types/OnCallDutyPolicy/OnCallCalendarFeedUtil.js +800 -0
- package/build/dist/Types/OnCallDutyPolicy/OnCallCalendarFeedUtil.js.map +1 -0
- package/build/dist/Types/OnCallDutyPolicy/ScheduleShiftUtil.js +97 -3
- package/build/dist/Types/OnCallDutyPolicy/ScheduleShiftUtil.js.map +1 -1
- package/build/dist/Types/OnCallDutyPolicy/ShiftSeamUtil.js +77 -0
- package/build/dist/Types/OnCallDutyPolicy/ShiftSeamUtil.js.map +1 -0
- package/build/dist/Types/Rum/SessionReplay.js +38 -0
- package/build/dist/Types/Rum/SessionReplay.js.map +1 -1
- package/build/dist/UI/Components/Date/TimeRangePickerDropdown.js +9 -5
- package/build/dist/UI/Components/Date/TimeRangePickerDropdown.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/LogsViewer.js +12 -7
- package/build/dist/UI/Components/LogsViewer/LogsViewer.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/HistogramTooltip.js +15 -14
- package/build/dist/UI/Components/LogsViewer/components/HistogramTooltip.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogsAnalyticsView.js +17 -22
- package/build/dist/UI/Components/LogsViewer/components/LogsAnalyticsView.js.map +1 -1
- package/build/dist/UI/Components/LogsViewer/components/LogsHistogram.js +2 -4
- package/build/dist/UI/Components/LogsViewer/components/LogsHistogram.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryHistogram.js +2 -4
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryHistogram.js.map +1 -1
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryHistogramTooltip.js +15 -14
- package/build/dist/UI/Components/TelemetryViewer/components/TelemetryHistogramTooltip.js.map +1 -1
- package/build/dist/UI/Utils/Navigation.js +30 -0
- package/build/dist/UI/Utils/Navigation.js.map +1 -1
- package/build/dist/Utils/Array.js +25 -0
- package/build/dist/Utils/Array.js.map +1 -1
- package/build/dist/Utils/CertificateReissue.js +97 -0
- package/build/dist/Utils/CertificateReissue.js.map +1 -0
- package/build/dist/Utils/Grok/Grok.js +324 -0
- package/build/dist/Utils/Grok/Grok.js.map +1 -0
- package/build/dist/Utils/Grok/GrokPatterns.js +112 -0
- package/build/dist/Utils/Grok/GrokPatterns.js.map +1 -0
- package/build/dist/Utils/Monitor/NetworkDeviceMonitorTemplateUtil.js +63 -3
- package/build/dist/Utils/Monitor/NetworkDeviceMonitorTemplateUtil.js.map +1 -1
- package/package.json +1 -1
- package/UI/Utils/JsonWebToken.ts +0 -14
- package/build/dist/UI/Utils/JsonWebToken.js +0 -10
- package/build/dist/UI/Utils/JsonWebToken.js.map +0 -1
|
@@ -1,10 +1,98 @@
|
|
|
1
1
|
import DatabaseService from "./DatabaseService";
|
|
2
2
|
import Model from "../../Models/DatabaseModels/LogPipelineProcessor";
|
|
3
|
+
import CreateBy from "../Types/Database/CreateBy";
|
|
4
|
+
import UpdateBy from "../Types/Database/UpdateBy";
|
|
5
|
+
import { OnCreate, OnUpdate } from "../Types/Database/Hooks";
|
|
6
|
+
import LIMIT_MAX from "../../Types/Database/LimitMax";
|
|
7
|
+
import { JSONObject } from "../../Types/JSON";
|
|
8
|
+
import { validateLogPipelineProcessor } from "../Utils/LogPipelineProcessorValidation";
|
|
9
|
+
|
|
10
|
+
/*
|
|
11
|
+
* `PartialEntity` values may be `() => string` raw SQL expressions rather
|
|
12
|
+
* than literals. One cannot be evaluated here, so an update that sets a
|
|
13
|
+
* validated field to an expression is skipped - validating a stringified
|
|
14
|
+
* function would be worse than not validating at all. Nothing in the
|
|
15
|
+
* product writes processor fields this way.
|
|
16
|
+
*/
|
|
17
|
+
function isSqlExpressionValue(value: unknown): boolean {
|
|
18
|
+
return typeof value === "function";
|
|
19
|
+
}
|
|
3
20
|
|
|
4
21
|
export class Service extends DatabaseService<Model> {
|
|
5
22
|
public constructor() {
|
|
6
23
|
super(Model);
|
|
7
24
|
}
|
|
25
|
+
|
|
26
|
+
protected override async onBeforeCreate(
|
|
27
|
+
createBy: CreateBy<Model>,
|
|
28
|
+
): Promise<OnCreate<Model>> {
|
|
29
|
+
validateLogPipelineProcessor({
|
|
30
|
+
processorType: createBy.data.processorType,
|
|
31
|
+
configuration: createBy.data.configuration as JSONObject | undefined,
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
return { createBy, carryForward: null };
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
protected override async onBeforeUpdate(
|
|
38
|
+
updateBy: UpdateBy<Model>,
|
|
39
|
+
): Promise<OnUpdate<Model>> {
|
|
40
|
+
/*
|
|
41
|
+
* An edit can break a row without naming both fields: switching
|
|
42
|
+
* `processorType` to GrokParser while the stored configuration is
|
|
43
|
+
* still a severity-remapper blob, or replacing the pattern on a row
|
|
44
|
+
* that is already a GrokParser. So validate the MERGED row.
|
|
45
|
+
*
|
|
46
|
+
* Only pay for the SELECT when the update touches one of them.
|
|
47
|
+
* Processor edits are rare, human-driven config changes - this is
|
|
48
|
+
* not a hot path.
|
|
49
|
+
*/
|
|
50
|
+
const incomingProcessorType: unknown = updateBy.data.processorType;
|
|
51
|
+
const incomingConfiguration: unknown = updateBy.data.configuration;
|
|
52
|
+
|
|
53
|
+
if (
|
|
54
|
+
incomingProcessorType === undefined &&
|
|
55
|
+
incomingConfiguration === undefined
|
|
56
|
+
) {
|
|
57
|
+
return { updateBy, carryForward: null };
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (
|
|
61
|
+
isSqlExpressionValue(incomingProcessorType) ||
|
|
62
|
+
isSqlExpressionValue(incomingConfiguration)
|
|
63
|
+
) {
|
|
64
|
+
return { updateBy, carryForward: null };
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const existingRows: Array<Model> = await this.findBy({
|
|
68
|
+
query: updateBy.query,
|
|
69
|
+
skip: 0,
|
|
70
|
+
limit: LIMIT_MAX,
|
|
71
|
+
select: {
|
|
72
|
+
_id: true,
|
|
73
|
+
processorType: true,
|
|
74
|
+
configuration: true,
|
|
75
|
+
},
|
|
76
|
+
props: {
|
|
77
|
+
isRoot: true,
|
|
78
|
+
},
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
for (const existing of existingRows) {
|
|
82
|
+
validateLogPipelineProcessor({
|
|
83
|
+
processorType:
|
|
84
|
+
incomingProcessorType !== undefined
|
|
85
|
+
? (incomingProcessorType as string | null)
|
|
86
|
+
: existing.processorType,
|
|
87
|
+
configuration:
|
|
88
|
+
incomingConfiguration !== undefined
|
|
89
|
+
? (incomingConfiguration as JSONObject | string | null)
|
|
90
|
+
: (existing.configuration as JSONObject | undefined),
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return { updateBy, carryForward: null };
|
|
95
|
+
}
|
|
8
96
|
}
|
|
9
97
|
|
|
10
98
|
export default new Service();
|
|
@@ -6,6 +6,7 @@ import { OnCreate, OnUpdate } from "../Types/Database/Hooks";
|
|
|
6
6
|
import MonitorStepsProjectValidator from "../Utils/Monitor/MonitorStepsProjectValidator";
|
|
7
7
|
import DatabaseCommonInteractionProps from "../../Types/BaseDatabase/DatabaseCommonInteractionProps";
|
|
8
8
|
import BadDataException from "../../Types/Exception/BadDataException";
|
|
9
|
+
import Includes from "../../Types/BaseDatabase/Includes";
|
|
9
10
|
import LIMIT_MAX from "../../Types/Database/LimitMax";
|
|
10
11
|
import { JSONObject } from "../../Types/JSON";
|
|
11
12
|
import MonitorSteps from "../../Types/Monitor/MonitorSteps";
|
|
@@ -275,7 +276,7 @@ export class Service extends DatabaseService<Model> {
|
|
|
275
276
|
monitorSteps: true,
|
|
276
277
|
autoProvisionedNetworkDeviceId: true,
|
|
277
278
|
},
|
|
278
|
-
sort: { createdAt: SortOrder.Ascending },
|
|
279
|
+
sort: { createdAt: SortOrder.Ascending, _id: SortOrder.Ascending },
|
|
279
280
|
limit: LIMIT_MAX,
|
|
280
281
|
skip: skip,
|
|
281
282
|
props: { isRoot: true },
|
|
@@ -321,16 +322,74 @@ export class Service extends DatabaseService<Model> {
|
|
|
321
322
|
return { totalLinkedMonitors, syncedMonitors };
|
|
322
323
|
}
|
|
323
324
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
325
|
+
/*
|
|
326
|
+
* A single updateBy is capped at its `limit`, so a template with more
|
|
327
|
+
* linked monitors than LIMIT_MAX used to leave the remainder on the old
|
|
328
|
+
* config and still return success. Offset paging cannot fix that here:
|
|
329
|
+
* updateBy takes no sort, and rewriting a row moves its tuple, so a
|
|
330
|
+
* second page at a higher skip can step over rows the first page moved.
|
|
331
|
+
* Page the ids first instead, then update by id batch.
|
|
332
|
+
*
|
|
333
|
+
* `_id` rides along in the sort because skip/limit paging is only stable
|
|
334
|
+
* over a total order: a fleet provisioned by one auto-import run shares a
|
|
335
|
+
* createdAt, and without the tiebreaker a tie straddling a page boundary
|
|
336
|
+
* returns one row twice and another never — which here would inflate
|
|
337
|
+
* syncedMonitors by exactly the number of rows it dropped.
|
|
338
|
+
*/
|
|
339
|
+
const linkedMonitorIds: Array<ObjectID> = [];
|
|
340
|
+
|
|
341
|
+
for (let skip: number = 0; ; skip += LIMIT_MAX) {
|
|
342
|
+
const monitors: Array<Monitor> = await MonitorService.findBy({
|
|
343
|
+
query: {
|
|
344
|
+
monitorTemplateId: template.id!,
|
|
345
|
+
projectId: template.projectId,
|
|
346
|
+
},
|
|
347
|
+
select: { _id: true },
|
|
348
|
+
sort: { createdAt: SortOrder.Ascending, _id: SortOrder.Ascending },
|
|
349
|
+
limit: LIMIT_MAX,
|
|
350
|
+
skip: skip,
|
|
351
|
+
props: { isRoot: true },
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
for (const monitor of monitors) {
|
|
355
|
+
linkedMonitorIds.push(monitor.id!);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
if (monitors.length < LIMIT_MAX) {
|
|
359
|
+
break;
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
let syncedMonitors: number = 0;
|
|
364
|
+
|
|
365
|
+
for (
|
|
366
|
+
let batchStart: number = 0;
|
|
367
|
+
batchStart < linkedMonitorIds.length;
|
|
368
|
+
batchStart += LIMIT_MAX
|
|
369
|
+
) {
|
|
370
|
+
const batch: Array<ObjectID> = linkedMonitorIds.slice(
|
|
371
|
+
batchStart,
|
|
372
|
+
batchStart + LIMIT_MAX,
|
|
373
|
+
);
|
|
374
|
+
|
|
375
|
+
/*
|
|
376
|
+
* Still scoped by template and project, so a stale id from the paging
|
|
377
|
+
* read above cannot widen the write beyond this template's fleet.
|
|
378
|
+
* props stays the caller's — updateBy narrows each batch to what they
|
|
379
|
+
* may actually update.
|
|
380
|
+
*/
|
|
381
|
+
syncedMonitors += await MonitorService.updateBy({
|
|
382
|
+
query: {
|
|
383
|
+
_id: new Includes(batch),
|
|
384
|
+
monitorTemplateId: template.id!,
|
|
385
|
+
projectId: template.projectId,
|
|
386
|
+
},
|
|
387
|
+
data: updateData as any,
|
|
388
|
+
limit: LIMIT_MAX,
|
|
389
|
+
skip: 0,
|
|
390
|
+
props: data.props,
|
|
391
|
+
});
|
|
392
|
+
}
|
|
334
393
|
|
|
335
394
|
return {
|
|
336
395
|
totalLinkedMonitors,
|
|
@@ -25,12 +25,35 @@ import { WhatsAppMessagePayload } from "../../Types/WhatsApp/WhatsAppMessage";
|
|
|
25
25
|
import OnCallDutyPolicyTimeLogService from "./OnCallDutyPolicyTimeLogService";
|
|
26
26
|
import OneUptimeDate from "../../Types/Date";
|
|
27
27
|
import logger, { LogAttributes } from "../Utils/Logger";
|
|
28
|
+
import { OnCallShiftChangeReason } from "../Utils/OnCall/OnCallShiftChangeListeners";
|
|
28
29
|
|
|
29
30
|
export class Service extends DatabaseService<Model> {
|
|
30
31
|
public constructor() {
|
|
31
32
|
super(Model);
|
|
32
33
|
}
|
|
33
34
|
|
|
35
|
+
/**
|
|
36
|
+
* Attaching to / detaching from a policy changes the schedule's policy
|
|
37
|
+
* context (which overrides apply, and which policies its calendar events
|
|
38
|
+
* list), so it is a configuration change for the calendar feeds and the
|
|
39
|
+
* reminders: bump shiftConfigVersion, purge the feed caches, notify the
|
|
40
|
+
* listeners. Runs after the roster refresh; never throws.
|
|
41
|
+
*/
|
|
42
|
+
private async propagateAttachmentChange(
|
|
43
|
+
onCallDutyPolicyScheduleId: ObjectID | null | undefined,
|
|
44
|
+
projectId: ObjectID | null | undefined,
|
|
45
|
+
): Promise<void> {
|
|
46
|
+
if (!onCallDutyPolicyScheduleId) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
await OnCallDutyPolicyScheduleService.propagateShiftConfigChange({
|
|
51
|
+
scheduleIds: [onCallDutyPolicyScheduleId],
|
|
52
|
+
projectId: projectId || null,
|
|
53
|
+
reason: OnCallShiftChangeReason.PolicyAttachmentChanged,
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
|
|
34
57
|
/**
|
|
35
58
|
* Re-resolve and persist the schedule's roster after it is attached to, or
|
|
36
59
|
* detached from, an on-call policy.
|
|
@@ -123,6 +146,11 @@ export class Service extends DatabaseService<Model> {
|
|
|
123
146
|
*/
|
|
124
147
|
await this.refreshScheduleRoster(createdModel.onCallDutyPolicyScheduleId);
|
|
125
148
|
|
|
149
|
+
await this.propagateAttachmentChange(
|
|
150
|
+
createdModel.onCallDutyPolicyScheduleId,
|
|
151
|
+
createdModel.projectId,
|
|
152
|
+
);
|
|
153
|
+
|
|
126
154
|
// send notification to the new current user.
|
|
127
155
|
|
|
128
156
|
const userOnSchedule: ObjectID | null =
|
|
@@ -387,6 +415,10 @@ export class Service extends DatabaseService<Model> {
|
|
|
387
415
|
}
|
|
388
416
|
refreshedScheduleIds.add(scheduleId);
|
|
389
417
|
await this.refreshScheduleRoster(deletedItem.onCallDutyPolicyScheduleId);
|
|
418
|
+
await this.propagateAttachmentChange(
|
|
419
|
+
deletedItem.onCallDutyPolicyScheduleId,
|
|
420
|
+
deletedItem.projectId,
|
|
421
|
+
);
|
|
390
422
|
}
|
|
391
423
|
|
|
392
424
|
for (const deletedItem of deletedItems) {
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
import CreateBy from "../Types/Database/CreateBy";
|
|
2
|
+
import UpdateBy from "../Types/Database/UpdateBy";
|
|
3
|
+
import { OnCreate, OnUpdate } from "../Types/Database/Hooks";
|
|
4
|
+
import DatabaseService from "./DatabaseService";
|
|
5
|
+
import OnCallDutyPolicyScheduleService from "./OnCallDutyPolicyScheduleService";
|
|
6
|
+
import CalendarFeedToken, {
|
|
7
|
+
CalendarFeedRotation,
|
|
8
|
+
} from "../Utils/OnCall/CalendarFeedToken";
|
|
9
|
+
import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
|
|
10
|
+
import Model from "../../Models/DatabaseModels/OnCallDutyPolicyScheduleCalendarFeed";
|
|
11
|
+
import OnCallDutyPolicySchedule from "../../Models/DatabaseModels/OnCallDutyPolicySchedule";
|
|
12
|
+
import LIMIT_MAX from "../../Types/Database/LimitMax";
|
|
13
|
+
import BadDataException from "../../Types/Exception/BadDataException";
|
|
14
|
+
import NotFoundException from "../../Types/Exception/NotFoundException";
|
|
15
|
+
import CalendarFeedWindow from "../../Types/OnCallDutyPolicy/CalendarFeedWindow";
|
|
16
|
+
import ObjectID from "../../Types/ObjectID";
|
|
17
|
+
import PositiveNumber from "../../Types/PositiveNumber";
|
|
18
|
+
|
|
19
|
+
/*
|
|
20
|
+
* Bounds for the coverage-gap threshold: a gap shorter than a minute is a
|
|
21
|
+
* seam artefact, and a threshold longer than a week would never emit.
|
|
22
|
+
*/
|
|
23
|
+
export const MIN_MINIMUM_GAP_MINUTES: number = 1;
|
|
24
|
+
export const MAX_MINIMUM_GAP_MINUTES: number = 7 * 24 * 60;
|
|
25
|
+
|
|
26
|
+
/*
|
|
27
|
+
* The shared, project-owned calendar feed of one on-call schedule.
|
|
28
|
+
*
|
|
29
|
+
* WHAT THE HOOKS GUARANTEE
|
|
30
|
+
*
|
|
31
|
+
* - The schedule exists in the caller's project. The foreign key alone
|
|
32
|
+
* would accept a schedule from another project (the FK does not know
|
|
33
|
+
* about tenants), and a feed that renders another project's roster to
|
|
34
|
+
* whoever holds this project's link is exactly the leak the tenant column
|
|
35
|
+
* exists to prevent.
|
|
36
|
+
* - One feed per schedule. The unique index enforces it at the database;
|
|
37
|
+
* the hook turns the constraint violation into a message a person can
|
|
38
|
+
* act on.
|
|
39
|
+
* - The token is minted HERE, on every create, whatever the request
|
|
40
|
+
* carried. Publishing a feed is a normal, permission-checked create
|
|
41
|
+
* (the schedule's Edit list), and the plaintext is then read back by the
|
|
42
|
+
* calendar API's `/current` route through the encrypted `token` column.
|
|
43
|
+
* - pastDays / futureDays are clamped and minimumGapMinutes is bounded on
|
|
44
|
+
* every write.
|
|
45
|
+
*
|
|
46
|
+
* rotateTokenById and rotateFeedsForMemberLeave are root writes for the
|
|
47
|
+
* calendar API and the team-member cleanup respectively; cache purging stays
|
|
48
|
+
* with the caller.
|
|
49
|
+
*/
|
|
50
|
+
export class Service extends DatabaseService<Model> {
|
|
51
|
+
public constructor() {
|
|
52
|
+
super(Model);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
@CaptureSpan()
|
|
56
|
+
protected override async onBeforeCreate(
|
|
57
|
+
createBy: CreateBy<Model>,
|
|
58
|
+
): Promise<OnCreate<Model>> {
|
|
59
|
+
const projectId: ObjectID | undefined =
|
|
60
|
+
createBy.data.projectId || createBy.props.tenantId;
|
|
61
|
+
|
|
62
|
+
if (!projectId) {
|
|
63
|
+
throw new BadDataException("projectId is required");
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const scheduleId: ObjectID | undefined =
|
|
67
|
+
createBy.data.onCallDutyPolicyScheduleId;
|
|
68
|
+
|
|
69
|
+
if (!scheduleId) {
|
|
70
|
+
throw new BadDataException("onCallDutyPolicyScheduleId is required");
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
createBy.data.projectId = projectId;
|
|
74
|
+
|
|
75
|
+
const schedule: OnCallDutyPolicySchedule | null =
|
|
76
|
+
await OnCallDutyPolicyScheduleService.findOneBy({
|
|
77
|
+
query: {
|
|
78
|
+
_id: scheduleId,
|
|
79
|
+
projectId: projectId,
|
|
80
|
+
},
|
|
81
|
+
select: {
|
|
82
|
+
_id: true,
|
|
83
|
+
},
|
|
84
|
+
props: {
|
|
85
|
+
isRoot: true,
|
|
86
|
+
ignoreHooks: true,
|
|
87
|
+
},
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
if (!schedule) {
|
|
91
|
+
throw new BadDataException("On-call schedule not found in this project.");
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const existing: PositiveNumber = await this.countBy({
|
|
95
|
+
query: {
|
|
96
|
+
onCallDutyPolicyScheduleId: scheduleId,
|
|
97
|
+
},
|
|
98
|
+
props: {
|
|
99
|
+
isRoot: true,
|
|
100
|
+
},
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
if (existing.toNumber() > 0) {
|
|
104
|
+
throw new BadDataException(
|
|
105
|
+
"This schedule already has a shared calendar feed. Regenerate or edit the existing one instead.",
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/*
|
|
110
|
+
* A request body never chooses the secret. Root callers (the calendar
|
|
111
|
+
* API) may pass a token they minted so they can answer with the URL in
|
|
112
|
+
* the same response; everyone else gets a fresh mint.
|
|
113
|
+
*/
|
|
114
|
+
CalendarFeedToken.applyTokenColumnsOnCreate(createBy.data, {
|
|
115
|
+
trustSuppliedToken: createBy.props.isRoot === true,
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
createBy.data.pastDays = CalendarFeedWindow.clampPastDays(
|
|
119
|
+
createBy.data.pastDays,
|
|
120
|
+
);
|
|
121
|
+
createBy.data.futureDays = CalendarFeedWindow.clampFutureDays(
|
|
122
|
+
createBy.data.futureDays,
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
if (createBy.data.minimumGapMinutes !== undefined) {
|
|
126
|
+
createBy.data.minimumGapMinutes = Service.validateMinimumGapMinutes(
|
|
127
|
+
createBy.data.minimumGapMinutes,
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
return { createBy, carryForward: null };
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
@CaptureSpan()
|
|
135
|
+
protected override async onBeforeUpdate(
|
|
136
|
+
updateBy: UpdateBy<Model>,
|
|
137
|
+
): Promise<OnUpdate<Model>> {
|
|
138
|
+
if (updateBy.data.pastDays !== undefined) {
|
|
139
|
+
updateBy.data.pastDays = CalendarFeedWindow.clampPastDays(
|
|
140
|
+
updateBy.data.pastDays,
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
if (updateBy.data.futureDays !== undefined) {
|
|
145
|
+
updateBy.data.futureDays = CalendarFeedWindow.clampFutureDays(
|
|
146
|
+
updateBy.data.futureDays,
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
if (updateBy.data.minimumGapMinutes !== undefined) {
|
|
151
|
+
updateBy.data.minimumGapMinutes = Service.validateMinimumGapMinutes(
|
|
152
|
+
updateBy.data.minimumGapMinutes,
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return { updateBy, carryForward: null };
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/*
|
|
160
|
+
* A whole number of minutes between MIN_MINIMUM_GAP_MINUTES and
|
|
161
|
+
* MAX_MINIMUM_GAP_MINUTES. Numeric strings are accepted because a root
|
|
162
|
+
* caller may hand over what a form posted; anything else is a 400.
|
|
163
|
+
*/
|
|
164
|
+
public static validateMinimumGapMinutes(value: unknown): number {
|
|
165
|
+
const parsed: number =
|
|
166
|
+
typeof value === "string" && value.trim() !== ""
|
|
167
|
+
? Number(value)
|
|
168
|
+
: (value as number);
|
|
169
|
+
|
|
170
|
+
if (
|
|
171
|
+
typeof parsed !== "number" ||
|
|
172
|
+
!Number.isInteger(parsed) ||
|
|
173
|
+
parsed < MIN_MINIMUM_GAP_MINUTES ||
|
|
174
|
+
parsed > MAX_MINIMUM_GAP_MINUTES
|
|
175
|
+
) {
|
|
176
|
+
throw new BadDataException(
|
|
177
|
+
`Minimum gap must be a whole number of minutes between ${MIN_MINIMUM_GAP_MINUTES} and ${MAX_MINIMUM_GAP_MINUTES}.`,
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
return parsed;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/**
|
|
185
|
+
* Rotate the token of an existing feed: mint a new one, move the current
|
|
186
|
+
* hash into the 30-day grace slot, stamp rotatedAt. Returns the new
|
|
187
|
+
* plaintext token ONCE. Root write; the caller purges caches.
|
|
188
|
+
*/
|
|
189
|
+
@CaptureSpan()
|
|
190
|
+
public async rotateTokenById(data: {
|
|
191
|
+
id: ObjectID;
|
|
192
|
+
}): Promise<CalendarFeedRotation> {
|
|
193
|
+
const existing: Model | null = await this.findOneBy({
|
|
194
|
+
query: { _id: data.id },
|
|
195
|
+
select: { _id: true, tokenHash: true },
|
|
196
|
+
props: { isRoot: true, ignoreHooks: true },
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
if (!existing) {
|
|
200
|
+
throw new NotFoundException("Calendar feed not found.");
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
const rotation: CalendarFeedRotation = CalendarFeedToken.buildRotation({
|
|
204
|
+
currentTokenHash: existing.tokenHash,
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
await this.updateOneById({
|
|
208
|
+
id: data.id,
|
|
209
|
+
data: CalendarFeedToken.toRotationUpdateData(rotation),
|
|
210
|
+
props: { isRoot: true },
|
|
211
|
+
});
|
|
212
|
+
|
|
213
|
+
return rotation;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Rotate every ENABLED feed in the project that opted into
|
|
218
|
+
* rotateWhenMemberLeaves. Called by the team-member cleanup when a user's
|
|
219
|
+
* last team membership in the project goes away. Returns the ids rotated
|
|
220
|
+
* so the caller can purge their caches. A disabled feed is left alone: it
|
|
221
|
+
* already serves an empty calendar, and rotating it would only reset the
|
|
222
|
+
* grace clock on a link nobody should be refreshing anyway.
|
|
223
|
+
*/
|
|
224
|
+
@CaptureSpan()
|
|
225
|
+
public async rotateFeedsForMemberLeave(data: {
|
|
226
|
+
projectId: ObjectID;
|
|
227
|
+
}): Promise<Array<ObjectID>> {
|
|
228
|
+
const feeds: Array<Model> = await this.findBy({
|
|
229
|
+
query: {
|
|
230
|
+
projectId: data.projectId,
|
|
231
|
+
isEnabled: true,
|
|
232
|
+
rotateWhenMemberLeaves: true,
|
|
233
|
+
},
|
|
234
|
+
select: {
|
|
235
|
+
_id: true,
|
|
236
|
+
},
|
|
237
|
+
limit: LIMIT_MAX,
|
|
238
|
+
skip: 0,
|
|
239
|
+
props: {
|
|
240
|
+
isRoot: true,
|
|
241
|
+
ignoreHooks: true,
|
|
242
|
+
},
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
const rotated: Array<ObjectID> = [];
|
|
246
|
+
|
|
247
|
+
for (const feed of feeds) {
|
|
248
|
+
if (!feed.id) {
|
|
249
|
+
continue;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
await this.rotateTokenById({ id: feed.id });
|
|
253
|
+
rotated.push(feed.id);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
return rotated;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
export default new Service();
|
|
@@ -17,12 +17,61 @@ import UpdateBy from "../Types/Database/UpdateBy";
|
|
|
17
17
|
import Model from "../../Models/DatabaseModels/OnCallDutyPolicyScheduleLayer";
|
|
18
18
|
import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
|
|
19
19
|
import OnCallDutyPolicyScheduleService from "./OnCallDutyPolicyScheduleService";
|
|
20
|
+
import { OnCallShiftChangeReason } from "../Utils/OnCall/OnCallShiftChangeListeners";
|
|
21
|
+
import logger from "../Utils/Logger";
|
|
20
22
|
|
|
21
23
|
export class Service extends DatabaseService<Model> {
|
|
22
24
|
public constructor() {
|
|
23
25
|
super(Model);
|
|
24
26
|
}
|
|
25
27
|
|
|
28
|
+
/*
|
|
29
|
+
* A layer edit changes who is on call and when for the whole schedule:
|
|
30
|
+
* bump its shiftConfigVersion, drop the calendar-feed caches and let the
|
|
31
|
+
* shift-change listeners re-plan. Runs AFTER the roster refresh so a
|
|
32
|
+
* listener that re-materializes sees the new configuration. Best-effort by
|
|
33
|
+
* construction (propagateShiftConfigChange never throws).
|
|
34
|
+
*/
|
|
35
|
+
private async propagateLayerChange(
|
|
36
|
+
scheduleId: ObjectID | null | undefined,
|
|
37
|
+
projectId: ObjectID | null | undefined,
|
|
38
|
+
): Promise<void> {
|
|
39
|
+
if (!scheduleId) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
await OnCallDutyPolicyScheduleService.propagateShiftConfigChange({
|
|
44
|
+
scheduleIds: [scheduleId],
|
|
45
|
+
projectId: projectId || null,
|
|
46
|
+
reason: OnCallShiftChangeReason.LayerChanged,
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Re-resolve and persist the schedule's roster after a layer change.
|
|
52
|
+
* Best-effort: the row is already committed when the success hooks run, so
|
|
53
|
+
* a throwing refresh (a concurrently-deleted schedule, a transient
|
|
54
|
+
* persistence or notification failure) must not abort the hook before
|
|
55
|
+
* propagateLayerChange bumps the shiftConfigVersion and purges the feed
|
|
56
|
+
* caches — otherwise the caches would keep serving the pre-edit roster for
|
|
57
|
+
* up to their TTL and the reminder change pass would be skipped. Mirrors
|
|
58
|
+
* OnCallDutyPolicyEscalationRuleScheduleService.refreshScheduleRoster.
|
|
59
|
+
*/
|
|
60
|
+
private async refreshScheduleRosterBestEffort(
|
|
61
|
+
scheduleId: ObjectID,
|
|
62
|
+
): Promise<void> {
|
|
63
|
+
try {
|
|
64
|
+
await OnCallDutyPolicyScheduleService.refreshCurrentUserIdAndHandoffTimeInSchedule(
|
|
65
|
+
scheduleId,
|
|
66
|
+
);
|
|
67
|
+
} catch (err) {
|
|
68
|
+
logger.error(
|
|
69
|
+
"Error refreshing the schedule roster after a layer change (best-effort).",
|
|
70
|
+
);
|
|
71
|
+
logger.error(err);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
26
75
|
/*
|
|
27
76
|
* A rotation interval count of 0 / NaN / negative breaks the handoff math
|
|
28
77
|
* (division by zero, Invalid Date), so reject it at the persistence boundary.
|
|
@@ -153,6 +202,7 @@ export class Service extends DatabaseService<Model> {
|
|
|
153
202
|
id: createdItem.id!,
|
|
154
203
|
select: {
|
|
155
204
|
onCallDutyPolicyScheduleId: true,
|
|
205
|
+
projectId: true,
|
|
156
206
|
},
|
|
157
207
|
props: {
|
|
158
208
|
isRoot: true,
|
|
@@ -163,8 +213,13 @@ export class Service extends DatabaseService<Model> {
|
|
|
163
213
|
return createdItem;
|
|
164
214
|
}
|
|
165
215
|
|
|
166
|
-
await
|
|
216
|
+
await this.refreshScheduleRosterBestEffort(
|
|
217
|
+
resource.onCallDutyPolicyScheduleId,
|
|
218
|
+
);
|
|
219
|
+
|
|
220
|
+
await this.propagateLayerChange(
|
|
167
221
|
resource.onCallDutyPolicyScheduleId,
|
|
222
|
+
resource.projectId,
|
|
168
223
|
);
|
|
169
224
|
|
|
170
225
|
return createdItem;
|
|
@@ -192,6 +247,7 @@ export class Service extends DatabaseService<Model> {
|
|
|
192
247
|
id: item,
|
|
193
248
|
select: {
|
|
194
249
|
onCallDutyPolicyScheduleId: true,
|
|
250
|
+
projectId: true,
|
|
195
251
|
},
|
|
196
252
|
props: {
|
|
197
253
|
isRoot: true,
|
|
@@ -202,8 +258,13 @@ export class Service extends DatabaseService<Model> {
|
|
|
202
258
|
continue;
|
|
203
259
|
}
|
|
204
260
|
|
|
205
|
-
await
|
|
261
|
+
await this.refreshScheduleRosterBestEffort(
|
|
262
|
+
resource.onCallDutyPolicyScheduleId,
|
|
263
|
+
);
|
|
264
|
+
|
|
265
|
+
await this.propagateLayerChange(
|
|
206
266
|
resource.onCallDutyPolicyScheduleId,
|
|
267
|
+
resource.projectId,
|
|
207
268
|
);
|
|
208
269
|
}
|
|
209
270
|
|
|
@@ -245,6 +306,7 @@ export class Service extends DatabaseService<Model> {
|
|
|
245
306
|
select: {
|
|
246
307
|
order: true,
|
|
247
308
|
onCallDutyPolicyScheduleId: true,
|
|
309
|
+
projectId: true,
|
|
248
310
|
},
|
|
249
311
|
});
|
|
250
312
|
}
|
|
@@ -271,8 +333,13 @@ export class Service extends DatabaseService<Model> {
|
|
|
271
333
|
false,
|
|
272
334
|
);
|
|
273
335
|
|
|
274
|
-
await
|
|
336
|
+
await this.refreshScheduleRosterBestEffort(
|
|
337
|
+
resource.onCallDutyPolicyScheduleId,
|
|
338
|
+
);
|
|
339
|
+
|
|
340
|
+
await this.propagateLayerChange(
|
|
275
341
|
resource.onCallDutyPolicyScheduleId,
|
|
342
|
+
resource.projectId,
|
|
276
343
|
);
|
|
277
344
|
}
|
|
278
345
|
}
|