@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
|
@@ -18,12 +18,124 @@ import Timezone from "../../Types/Timezone";
|
|
|
18
18
|
import DeleteBy from "../Types/Database/DeleteBy";
|
|
19
19
|
import { LIMIT_PER_PROJECT } from "../../Types/Database/LimitMax";
|
|
20
20
|
import logger from "../Utils/Logger";
|
|
21
|
+
import { OnCallShiftChangeReason } from "../Utils/OnCall/OnCallShiftChangeListeners";
|
|
22
|
+
|
|
23
|
+
/*
|
|
24
|
+
* The (project, overridden user, substitute) triple an override names; the
|
|
25
|
+
* hooks capture it before an update / delete so the schedules of the OLD
|
|
26
|
+
* users can be refreshed and re-versioned once the row has changed.
|
|
27
|
+
*/
|
|
28
|
+
interface OverrideUserPair {
|
|
29
|
+
projectId: ObjectID;
|
|
30
|
+
overrideUserId: ObjectID;
|
|
31
|
+
routeAlertsToUserId?: ObjectID | undefined;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/*
|
|
35
|
+
* The subset of OnCallDutyPolicyScheduleService the override hooks call.
|
|
36
|
+
* Lazily required (see refreshRostersForOverrideUser) because that service
|
|
37
|
+
* imports this one.
|
|
38
|
+
*/
|
|
39
|
+
interface ScheduleServiceForOverrides {
|
|
40
|
+
refreshRostersForUserInProject: (d: {
|
|
41
|
+
projectId: ObjectID;
|
|
42
|
+
userId: ObjectID;
|
|
43
|
+
}) => Promise<void>;
|
|
44
|
+
getScheduleIdsForUsersInProject: (d: {
|
|
45
|
+
projectId: ObjectID;
|
|
46
|
+
userIds: Array<ObjectID>;
|
|
47
|
+
}) => Promise<Array<ObjectID>>;
|
|
48
|
+
propagateShiftConfigChange: (d: {
|
|
49
|
+
scheduleIds: Array<ObjectID>;
|
|
50
|
+
projectId?: ObjectID | null | undefined;
|
|
51
|
+
userIds?: Array<ObjectID> | undefined;
|
|
52
|
+
reason: OnCallShiftChangeReason;
|
|
53
|
+
}) => Promise<void>;
|
|
54
|
+
}
|
|
21
55
|
|
|
22
56
|
export class Service extends DatabaseService<OnCallDutyPolicyUserOverride> {
|
|
23
57
|
public constructor() {
|
|
24
58
|
super(OnCallDutyPolicyUserOverride);
|
|
25
59
|
}
|
|
26
60
|
|
|
61
|
+
private getScheduleService(): ScheduleServiceForOverrides {
|
|
62
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires
|
|
63
|
+
return require("./OnCallDutyPolicyScheduleService").default;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* An override changes who is on call on every schedule that contains the
|
|
68
|
+
* overridden user, and it changes the SUBSTITUTE's personal calendar too.
|
|
69
|
+
* Find those schedules with the same layer-user query the roster refresh
|
|
70
|
+
* uses (for every overridden user, old and new), then bump their
|
|
71
|
+
* shiftConfigVersion, drop the feed caches — the substitutes' personal
|
|
72
|
+
* caches included — and let the shift-change listeners re-plan reminders.
|
|
73
|
+
* One call per project; best-effort, never throws into the CRUD path.
|
|
74
|
+
*/
|
|
75
|
+
private async propagateShiftChangeForOverrides(
|
|
76
|
+
pairs: Array<OverrideUserPair>,
|
|
77
|
+
): Promise<void> {
|
|
78
|
+
const byProject: Map<
|
|
79
|
+
string,
|
|
80
|
+
{
|
|
81
|
+
projectId: ObjectID;
|
|
82
|
+
overrideUserIds: Array<ObjectID>;
|
|
83
|
+
allUserIds: Array<ObjectID>;
|
|
84
|
+
}
|
|
85
|
+
> = new Map();
|
|
86
|
+
|
|
87
|
+
for (const pair of pairs) {
|
|
88
|
+
if (!pair.projectId || !pair.overrideUserId) {
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const key: string = pair.projectId.toString();
|
|
93
|
+
const entry: {
|
|
94
|
+
projectId: ObjectID;
|
|
95
|
+
overrideUserIds: Array<ObjectID>;
|
|
96
|
+
allUserIds: Array<ObjectID>;
|
|
97
|
+
} = byProject.get(key) || {
|
|
98
|
+
projectId: pair.projectId,
|
|
99
|
+
overrideUserIds: [],
|
|
100
|
+
allUserIds: [],
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
entry.overrideUserIds.push(pair.overrideUserId);
|
|
104
|
+
entry.allUserIds.push(pair.overrideUserId);
|
|
105
|
+
|
|
106
|
+
if (pair.routeAlertsToUserId) {
|
|
107
|
+
entry.allUserIds.push(pair.routeAlertsToUserId);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
byProject.set(key, entry);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
for (const entry of byProject.values()) {
|
|
114
|
+
try {
|
|
115
|
+
const scheduleService: ScheduleServiceForOverrides =
|
|
116
|
+
this.getScheduleService();
|
|
117
|
+
|
|
118
|
+
const scheduleIds: Array<ObjectID> =
|
|
119
|
+
await scheduleService.getScheduleIdsForUsersInProject({
|
|
120
|
+
projectId: entry.projectId,
|
|
121
|
+
userIds: entry.overrideUserIds,
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
await scheduleService.propagateShiftConfigChange({
|
|
125
|
+
scheduleIds,
|
|
126
|
+
projectId: entry.projectId,
|
|
127
|
+
userIds: entry.allUserIds,
|
|
128
|
+
reason: OnCallShiftChangeReason.OverrideChanged,
|
|
129
|
+
});
|
|
130
|
+
} catch (err) {
|
|
131
|
+
logger.error(
|
|
132
|
+
"Error propagating a user override change to the calendar feeds (best-effort).",
|
|
133
|
+
);
|
|
134
|
+
logger.error(err);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
27
139
|
/**
|
|
28
140
|
* Re-resolve the persisted roster of every schedule in the project that
|
|
29
141
|
* contains the override user, so a created / updated / deleted override is
|
|
@@ -41,13 +153,8 @@ export class Service extends DatabaseService<OnCallDutyPolicyUserOverride> {
|
|
|
41
153
|
}
|
|
42
154
|
|
|
43
155
|
try {
|
|
44
|
-
const scheduleService:
|
|
45
|
-
|
|
46
|
-
projectId: ObjectID;
|
|
47
|
-
userId: ObjectID;
|
|
48
|
-
}) => Promise<void>;
|
|
49
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires
|
|
50
|
-
} = require("./OnCallDutyPolicyScheduleService").default;
|
|
156
|
+
const scheduleService: ScheduleServiceForOverrides =
|
|
157
|
+
this.getScheduleService();
|
|
51
158
|
|
|
52
159
|
await scheduleService.refreshRostersForUserInProject({
|
|
53
160
|
projectId: data.projectId,
|
|
@@ -190,6 +297,16 @@ export class Service extends DatabaseService<OnCallDutyPolicyUserOverride> {
|
|
|
190
297
|
overrideUserId,
|
|
191
298
|
});
|
|
192
299
|
|
|
300
|
+
if (projectId && overrideUserId) {
|
|
301
|
+
await this.propagateShiftChangeForOverrides([
|
|
302
|
+
{
|
|
303
|
+
projectId,
|
|
304
|
+
overrideUserId,
|
|
305
|
+
routeAlertsToUserId: routeAlertsToUserId || undefined,
|
|
306
|
+
},
|
|
307
|
+
]);
|
|
308
|
+
}
|
|
309
|
+
|
|
193
310
|
return createdItem;
|
|
194
311
|
}
|
|
195
312
|
|
|
@@ -207,10 +324,7 @@ export class Service extends DatabaseService<OnCallDutyPolicyUserOverride> {
|
|
|
207
324
|
* schedules by the NEW user only (audit M2). Mirrors the onBeforeDelete
|
|
208
325
|
* carry-forward pattern used by the delete path.
|
|
209
326
|
*/
|
|
210
|
-
const previous: Array<
|
|
211
|
-
projectId: ObjectID;
|
|
212
|
-
overrideUserId: ObjectID;
|
|
213
|
-
}> = [];
|
|
327
|
+
const previous: Array<OverrideUserPair> = [];
|
|
214
328
|
|
|
215
329
|
try {
|
|
216
330
|
const rows: Array<OnCallDutyPolicyUserOverride> = await this.findBy({
|
|
@@ -218,6 +332,7 @@ export class Service extends DatabaseService<OnCallDutyPolicyUserOverride> {
|
|
|
218
332
|
select: {
|
|
219
333
|
projectId: true,
|
|
220
334
|
overrideUserId: true,
|
|
335
|
+
routeAlertsToUserId: true,
|
|
221
336
|
},
|
|
222
337
|
props: {
|
|
223
338
|
isRoot: true,
|
|
@@ -231,8 +346,14 @@ export class Service extends DatabaseService<OnCallDutyPolicyUserOverride> {
|
|
|
231
346
|
row.projectId || row.project?.id;
|
|
232
347
|
const overrideUserId: ObjectID | undefined | null =
|
|
233
348
|
row.overrideUserId || row.overrideUser?.id;
|
|
349
|
+
const routeAlertsToUserId: ObjectID | undefined | null =
|
|
350
|
+
row.routeAlertsToUserId || row.routeAlertsToUser?.id;
|
|
234
351
|
if (projectId && overrideUserId) {
|
|
235
|
-
previous.push({
|
|
352
|
+
previous.push({
|
|
353
|
+
projectId,
|
|
354
|
+
overrideUserId,
|
|
355
|
+
routeAlertsToUserId: routeAlertsToUserId || undefined,
|
|
356
|
+
});
|
|
236
357
|
}
|
|
237
358
|
}
|
|
238
359
|
} catch (err) {
|
|
@@ -279,11 +400,11 @@ export class Service extends DatabaseService<OnCallDutyPolicyUserOverride> {
|
|
|
279
400
|
};
|
|
280
401
|
|
|
281
402
|
// OLD override users captured before the update.
|
|
282
|
-
const previous: Array<
|
|
283
|
-
(onUpdate.carryForward as Array<
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
403
|
+
const previous: Array<OverrideUserPair> =
|
|
404
|
+
(onUpdate.carryForward as Array<OverrideUserPair>) || [];
|
|
405
|
+
|
|
406
|
+
// Everyone the edit touched, old and new, for the feed / reminder pass.
|
|
407
|
+
const affectedPairs: Array<OverrideUserPair> = [...previous];
|
|
287
408
|
|
|
288
409
|
for (const entry of previous) {
|
|
289
410
|
await refreshPair(entry.projectId, entry.overrideUserId);
|
|
@@ -296,6 +417,7 @@ export class Service extends DatabaseService<OnCallDutyPolicyUserOverride> {
|
|
|
296
417
|
select: {
|
|
297
418
|
projectId: true,
|
|
298
419
|
overrideUserId: true,
|
|
420
|
+
routeAlertsToUserId: true,
|
|
299
421
|
},
|
|
300
422
|
props: {
|
|
301
423
|
isRoot: true,
|
|
@@ -306,12 +428,26 @@ export class Service extends DatabaseService<OnCallDutyPolicyUserOverride> {
|
|
|
306
428
|
continue;
|
|
307
429
|
}
|
|
308
430
|
|
|
309
|
-
|
|
310
|
-
item.projectId || item.project?.id
|
|
311
|
-
|
|
312
|
-
|
|
431
|
+
const newProjectId: ObjectID | undefined | null =
|
|
432
|
+
item.projectId || item.project?.id;
|
|
433
|
+
const newOverrideUserId: ObjectID | undefined | null =
|
|
434
|
+
item.overrideUserId || item.overrideUser?.id;
|
|
435
|
+
const newRouteAlertsToUserId: ObjectID | undefined | null =
|
|
436
|
+
item.routeAlertsToUserId || item.routeAlertsToUser?.id;
|
|
437
|
+
|
|
438
|
+
await refreshPair(newProjectId, newOverrideUserId);
|
|
439
|
+
|
|
440
|
+
if (newProjectId && newOverrideUserId) {
|
|
441
|
+
affectedPairs.push({
|
|
442
|
+
projectId: newProjectId,
|
|
443
|
+
overrideUserId: newOverrideUserId,
|
|
444
|
+
routeAlertsToUserId: newRouteAlertsToUserId || undefined,
|
|
445
|
+
});
|
|
446
|
+
}
|
|
313
447
|
}
|
|
314
448
|
|
|
449
|
+
await this.propagateShiftChangeForOverrides(affectedPairs);
|
|
450
|
+
|
|
315
451
|
return onUpdate;
|
|
316
452
|
}
|
|
317
453
|
|
|
@@ -326,11 +462,8 @@ export class Service extends DatabaseService<OnCallDutyPolicyUserOverride> {
|
|
|
326
462
|
* than waiting for the next natural handoff (audit F4). The affected
|
|
327
463
|
* project/user pairs were captured in onBeforeDelete (the rows are gone now).
|
|
328
464
|
*/
|
|
329
|
-
const affected: Array<
|
|
330
|
-
(onDelete.carryForward as Array<
|
|
331
|
-
projectId: ObjectID;
|
|
332
|
-
overrideUserId: ObjectID;
|
|
333
|
-
}>) || [];
|
|
465
|
+
const affected: Array<OverrideUserPair> =
|
|
466
|
+
(onDelete.carryForward as Array<OverrideUserPair>) || [];
|
|
334
467
|
|
|
335
468
|
for (const entry of affected) {
|
|
336
469
|
await this.refreshRostersForOverrideUser({
|
|
@@ -339,6 +472,8 @@ export class Service extends DatabaseService<OnCallDutyPolicyUserOverride> {
|
|
|
339
472
|
});
|
|
340
473
|
}
|
|
341
474
|
|
|
475
|
+
await this.propagateShiftChangeForOverrides(affected);
|
|
476
|
+
|
|
342
477
|
return onDelete;
|
|
343
478
|
}
|
|
344
479
|
|
|
@@ -368,10 +503,7 @@ export class Service extends DatabaseService<OnCallDutyPolicyUserOverride> {
|
|
|
368
503
|
* onDeleteSuccess can refresh those schedules' rosters AFTER the rows are
|
|
369
504
|
* gone (audit F4). Collected for global overrides too (no policy id).
|
|
370
505
|
*/
|
|
371
|
-
const affectedRosters: Array<
|
|
372
|
-
projectId: ObjectID;
|
|
373
|
-
overrideUserId: ObjectID;
|
|
374
|
-
}> = [];
|
|
506
|
+
const affectedRosters: Array<OverrideUserPair> = [];
|
|
375
507
|
|
|
376
508
|
for (const item of itemsToDelete) {
|
|
377
509
|
const onCallDutyPolicyId: ObjectID | undefined | null =
|
|
@@ -387,7 +519,11 @@ export class Service extends DatabaseService<OnCallDutyPolicyUserOverride> {
|
|
|
387
519
|
item.routeAlertsToUserId || item.routeAlertsToUser?.id;
|
|
388
520
|
|
|
389
521
|
if (projectId && overrideUserId) {
|
|
390
|
-
affectedRosters.push({
|
|
522
|
+
affectedRosters.push({
|
|
523
|
+
projectId,
|
|
524
|
+
overrideUserId,
|
|
525
|
+
routeAlertsToUserId: routeAlertsToUserId || undefined,
|
|
526
|
+
});
|
|
391
527
|
}
|
|
392
528
|
|
|
393
529
|
if (
|
|
@@ -0,0 +1,192 @@
|
|
|
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 {
|
|
6
|
+
MAX_MINIMUM_GAP_MINUTES,
|
|
7
|
+
MIN_MINIMUM_GAP_MINUTES,
|
|
8
|
+
} from "./OnCallDutyPolicyScheduleCalendarFeedService";
|
|
9
|
+
import CalendarFeedToken, {
|
|
10
|
+
CalendarFeedRotation,
|
|
11
|
+
} from "../Utils/OnCall/CalendarFeedToken";
|
|
12
|
+
import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
|
|
13
|
+
import Model from "../../Models/DatabaseModels/ProjectOnCallCalendarFeed";
|
|
14
|
+
import BadDataException from "../../Types/Exception/BadDataException";
|
|
15
|
+
import NotFoundException from "../../Types/Exception/NotFoundException";
|
|
16
|
+
import CalendarFeedWindow from "../../Types/OnCallDutyPolicy/CalendarFeedWindow";
|
|
17
|
+
import ObjectID from "../../Types/ObjectID";
|
|
18
|
+
import PositiveNumber from "../../Types/PositiveNumber";
|
|
19
|
+
|
|
20
|
+
/*
|
|
21
|
+
* The project-wide shared calendar feed: at most one row per project.
|
|
22
|
+
*
|
|
23
|
+
* The same guarantees as OnCallDutyPolicyScheduleCalendarFeedService minus
|
|
24
|
+
* the schedule check: one feed per project (unique index + a readable
|
|
25
|
+
* message), the token minted here on every create whatever the request
|
|
26
|
+
* carried, window and gap settings bounded on every write, root-only
|
|
27
|
+
* rotation with the 30-day grace hash.
|
|
28
|
+
*/
|
|
29
|
+
export class Service extends DatabaseService<Model> {
|
|
30
|
+
public constructor() {
|
|
31
|
+
super(Model);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
@CaptureSpan()
|
|
35
|
+
protected override async onBeforeCreate(
|
|
36
|
+
createBy: CreateBy<Model>,
|
|
37
|
+
): Promise<OnCreate<Model>> {
|
|
38
|
+
const projectId: ObjectID | undefined =
|
|
39
|
+
createBy.data.projectId || createBy.props.tenantId;
|
|
40
|
+
|
|
41
|
+
if (!projectId) {
|
|
42
|
+
throw new BadDataException("projectId is required");
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
createBy.data.projectId = projectId;
|
|
46
|
+
|
|
47
|
+
const existing: PositiveNumber = await this.countBy({
|
|
48
|
+
query: {
|
|
49
|
+
projectId: projectId,
|
|
50
|
+
},
|
|
51
|
+
props: {
|
|
52
|
+
isRoot: true,
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
if (existing.toNumber() > 0) {
|
|
57
|
+
throw new BadDataException(
|
|
58
|
+
"This project already has a shared calendar feed. Regenerate or edit the existing one instead.",
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// A request body never chooses the secret; only root may pre-mint one.
|
|
63
|
+
CalendarFeedToken.applyTokenColumnsOnCreate(createBy.data, {
|
|
64
|
+
trustSuppliedToken: createBy.props.isRoot === true,
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
createBy.data.pastDays = CalendarFeedWindow.clampPastDays(
|
|
68
|
+
createBy.data.pastDays,
|
|
69
|
+
);
|
|
70
|
+
createBy.data.futureDays = CalendarFeedWindow.clampFutureDays(
|
|
71
|
+
createBy.data.futureDays,
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
if (createBy.data.minimumGapMinutes !== undefined) {
|
|
75
|
+
createBy.data.minimumGapMinutes = Service.validateMinimumGapMinutes(
|
|
76
|
+
createBy.data.minimumGapMinutes,
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return { createBy, carryForward: null };
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
@CaptureSpan()
|
|
84
|
+
protected override async onBeforeUpdate(
|
|
85
|
+
updateBy: UpdateBy<Model>,
|
|
86
|
+
): Promise<OnUpdate<Model>> {
|
|
87
|
+
if (updateBy.data.pastDays !== undefined) {
|
|
88
|
+
updateBy.data.pastDays = CalendarFeedWindow.clampPastDays(
|
|
89
|
+
updateBy.data.pastDays,
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (updateBy.data.futureDays !== undefined) {
|
|
94
|
+
updateBy.data.futureDays = CalendarFeedWindow.clampFutureDays(
|
|
95
|
+
updateBy.data.futureDays,
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
if (updateBy.data.minimumGapMinutes !== undefined) {
|
|
100
|
+
updateBy.data.minimumGapMinutes = Service.validateMinimumGapMinutes(
|
|
101
|
+
updateBy.data.minimumGapMinutes,
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return { updateBy, carryForward: null };
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
public static validateMinimumGapMinutes(value: unknown): number {
|
|
109
|
+
const parsed: number =
|
|
110
|
+
typeof value === "string" && value.trim() !== ""
|
|
111
|
+
? Number(value)
|
|
112
|
+
: (value as number);
|
|
113
|
+
|
|
114
|
+
if (
|
|
115
|
+
typeof parsed !== "number" ||
|
|
116
|
+
!Number.isInteger(parsed) ||
|
|
117
|
+
parsed < MIN_MINIMUM_GAP_MINUTES ||
|
|
118
|
+
parsed > MAX_MINIMUM_GAP_MINUTES
|
|
119
|
+
) {
|
|
120
|
+
throw new BadDataException(
|
|
121
|
+
`Minimum gap must be a whole number of minutes between ${MIN_MINIMUM_GAP_MINUTES} and ${MAX_MINIMUM_GAP_MINUTES}.`,
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
return parsed;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Rotate the token of an existing feed. Returns the new plaintext token
|
|
130
|
+
* ONCE. Root write; the caller purges caches.
|
|
131
|
+
*/
|
|
132
|
+
@CaptureSpan()
|
|
133
|
+
public async rotateTokenById(data: {
|
|
134
|
+
id: ObjectID;
|
|
135
|
+
}): Promise<CalendarFeedRotation> {
|
|
136
|
+
const existing: Model | null = await this.findOneBy({
|
|
137
|
+
query: { _id: data.id },
|
|
138
|
+
select: { _id: true, tokenHash: true },
|
|
139
|
+
props: { isRoot: true, ignoreHooks: true },
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
if (!existing) {
|
|
143
|
+
throw new NotFoundException("Calendar feed not found.");
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const rotation: CalendarFeedRotation = CalendarFeedToken.buildRotation({
|
|
147
|
+
currentTokenHash: existing.tokenHash,
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
await this.updateOneById({
|
|
151
|
+
id: data.id,
|
|
152
|
+
data: CalendarFeedToken.toRotationUpdateData(rotation),
|
|
153
|
+
props: { isRoot: true },
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
return rotation;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Rotate the project's feed when a member leaves, if it is enabled and
|
|
161
|
+
* opted in. Returns the rotated id (at most one) for cache purging.
|
|
162
|
+
*/
|
|
163
|
+
@CaptureSpan()
|
|
164
|
+
public async rotateFeedsForMemberLeave(data: {
|
|
165
|
+
projectId: ObjectID;
|
|
166
|
+
}): Promise<Array<ObjectID>> {
|
|
167
|
+
const feed: Model | null = await this.findOneBy({
|
|
168
|
+
query: {
|
|
169
|
+
projectId: data.projectId,
|
|
170
|
+
isEnabled: true,
|
|
171
|
+
rotateWhenMemberLeaves: true,
|
|
172
|
+
},
|
|
173
|
+
select: {
|
|
174
|
+
_id: true,
|
|
175
|
+
},
|
|
176
|
+
props: {
|
|
177
|
+
isRoot: true,
|
|
178
|
+
ignoreHooks: true,
|
|
179
|
+
},
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
if (!feed || !feed.id) {
|
|
183
|
+
return [];
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
await this.rotateTokenById({ id: feed.id });
|
|
187
|
+
|
|
188
|
+
return [feed.id];
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
export default new Service();
|
|
@@ -20,10 +20,24 @@ import Telemetry, { Span } from "../Utils/Telemetry";
|
|
|
20
20
|
import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
|
|
21
21
|
import { StatusPageCNameRecord } from "../EnvironmentConfig";
|
|
22
22
|
import Domain from "../Types/Domain";
|
|
23
|
+
import ArrayUtil from "../../Utils/Array";
|
|
24
|
+
import OneUptimeDate from "../../Types/Date";
|
|
25
|
+
import CertificateReissueUtil from "../../Utils/CertificateReissue";
|
|
26
|
+
import TooManyRequestsException from "../../Types/Exception/TooManyRequestsException";
|
|
27
|
+
import QueryHelper from "../Types/Database/QueryHelper";
|
|
23
28
|
|
|
24
29
|
const STATUS_PAGE_DOMAIN_EGRESS_LABEL: string = "Status page domain";
|
|
25
30
|
|
|
26
31
|
export class Service extends DatabaseService<StatusPageDomain> {
|
|
32
|
+
/*
|
|
33
|
+
* How many status pages the provisioning sweep checks at once. Each check is
|
|
34
|
+
* one bounded request out to a customer domain, so this is about not letting
|
|
35
|
+
* the sweep's length grow with the size of the fleet, rather than about local
|
|
36
|
+
* work. Kept modest so a sweep cannot look like a burst of traffic to any
|
|
37
|
+
* shared infrastructure sitting in front of those domains.
|
|
38
|
+
*/
|
|
39
|
+
public static readonly SSL_PROVISIONING_CHECK_CONCURRENCY: number = 10;
|
|
40
|
+
|
|
27
41
|
public constructor() {
|
|
28
42
|
super(StatusPageDomain);
|
|
29
43
|
}
|
|
@@ -248,6 +262,133 @@ export class Service extends DatabaseService<StatusPageDomain> {
|
|
|
248
262
|
});
|
|
249
263
|
}
|
|
250
264
|
|
|
265
|
+
/*
|
|
266
|
+
* Reissue this domain's Let's Encrypt certificate because a customer asked
|
|
267
|
+
* for it, rather than because it is close to expiring.
|
|
268
|
+
*
|
|
269
|
+
* Every order spends from a Let's Encrypt account that is shared by the
|
|
270
|
+
* whole installation - including by the cron that keeps everybody else's
|
|
271
|
+
* certificates alive - so this is throttled to one request per domain per
|
|
272
|
+
* CertificateReissueUtil.COOLDOWN_IN_HOURS.
|
|
273
|
+
*
|
|
274
|
+
* Throws with a customer-readable reason for every refusal, so the API layer
|
|
275
|
+
* can hand the message straight back without classifying the failure:
|
|
276
|
+
* BadDataException for a domain that is not eligible at all, and
|
|
277
|
+
* TooManyRequestsException (429) for one that is simply too soon.
|
|
278
|
+
*/
|
|
279
|
+
@CaptureSpan()
|
|
280
|
+
public async reissueCert(domainId: ObjectID): Promise<void> {
|
|
281
|
+
const now: Date = OneUptimeDate.getCurrentDate();
|
|
282
|
+
|
|
283
|
+
const statusPageDomain: StatusPageDomain | null = await this.findOneBy({
|
|
284
|
+
query: {
|
|
285
|
+
_id: domainId.toString(),
|
|
286
|
+
},
|
|
287
|
+
select: {
|
|
288
|
+
_id: true,
|
|
289
|
+
fullDomain: true,
|
|
290
|
+
isCnameVerified: true,
|
|
291
|
+
isSslOrdered: true,
|
|
292
|
+
isCustomCertificate: true,
|
|
293
|
+
certificateReissueRequestedAt: true,
|
|
294
|
+
},
|
|
295
|
+
props: {
|
|
296
|
+
isRoot: true,
|
|
297
|
+
},
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
if (!statusPageDomain) {
|
|
301
|
+
throw new BadDataException("Domain not found.");
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
if (!statusPageDomain.fullDomain) {
|
|
305
|
+
throw new BadDataException(
|
|
306
|
+
"Unable to reissue certificate because domain is null",
|
|
307
|
+
);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/*
|
|
311
|
+
* Nothing to reissue: the certificate on a custom-certificate domain is
|
|
312
|
+
* the one the customer uploaded, and we have no way to obtain another.
|
|
313
|
+
*/
|
|
314
|
+
if (statusPageDomain.isCustomCertificate) {
|
|
315
|
+
throw new BadDataException(
|
|
316
|
+
"This domain uses a certificate you uploaded yourself, so there is no Let's Encrypt certificate to reissue. Please edit this domain and upload a new certificate instead.",
|
|
317
|
+
);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
if (!statusPageDomain.isCnameVerified) {
|
|
321
|
+
throw new BadDataException(
|
|
322
|
+
"CNAME is not verified. Please verify CNAME first before you reissue the SSL certificate.",
|
|
323
|
+
);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/*
|
|
327
|
+
* A domain that never ordered a certificate has nothing to reissue - the
|
|
328
|
+
* dashboard shows "Order Free SSL" for it, which is the correct button.
|
|
329
|
+
*/
|
|
330
|
+
if (!statusPageDomain.isSslOrdered) {
|
|
331
|
+
throw new BadDataException(
|
|
332
|
+
"No SSL certificate has been ordered for this domain yet. Please order one first.",
|
|
333
|
+
);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
/*
|
|
337
|
+
* Claim the cooldown before ordering anything, and claim it by putting the
|
|
338
|
+
* cooldown condition in the WHERE clause rather than in an `if` above the
|
|
339
|
+
* write. Two clicks that arrive together both read a row that is not
|
|
340
|
+
* cooling down; only the write can decide which one of them gets to spend
|
|
341
|
+
* the CA's allowance.
|
|
342
|
+
*
|
|
343
|
+
* The stamp goes down BEFORE the order and is never rolled back on
|
|
344
|
+
* failure. A rejected order still costs a validation attempt against the
|
|
345
|
+
* shared account, and a domain whose order fails is exactly the domain
|
|
346
|
+
* somebody presses again - so a failed attempt has to start the clock the
|
|
347
|
+
* same way a successful one does.
|
|
348
|
+
*/
|
|
349
|
+
const claimedRowCount: number = await this.updateOneBy({
|
|
350
|
+
query: {
|
|
351
|
+
_id: domainId.toString(),
|
|
352
|
+
certificateReissueRequestedAt: QueryHelper.lessThanEqualToOrNull(
|
|
353
|
+
CertificateReissueUtil.getCooldownCutoff(now),
|
|
354
|
+
),
|
|
355
|
+
},
|
|
356
|
+
data: {
|
|
357
|
+
certificateReissueRequestedAt: now,
|
|
358
|
+
},
|
|
359
|
+
props: {
|
|
360
|
+
isRoot: true,
|
|
361
|
+
},
|
|
362
|
+
});
|
|
363
|
+
|
|
364
|
+
if (claimedRowCount === 0) {
|
|
365
|
+
if (statusPageDomain.certificateReissueRequestedAt) {
|
|
366
|
+
throw new TooManyRequestsException(
|
|
367
|
+
CertificateReissueUtil.getCooldownMessage(
|
|
368
|
+
statusPageDomain.certificateReissueRequestedAt,
|
|
369
|
+
now,
|
|
370
|
+
),
|
|
371
|
+
);
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
/*
|
|
375
|
+
* The row matched the cooldown a moment ago and does not now: another
|
|
376
|
+
* request claimed it in between, or the domain was deleted. Either way
|
|
377
|
+
* the caller must not order.
|
|
378
|
+
*/
|
|
379
|
+
throw new BadDataException(
|
|
380
|
+
"Could not start a certificate reissue for this domain. Please refresh the page and try again.",
|
|
381
|
+
);
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
logger.debug(
|
|
385
|
+
"Reissuing SSL certificate for domain: " + statusPageDomain.fullDomain,
|
|
386
|
+
{ fullDomain: statusPageDomain.fullDomain } as LogAttributes,
|
|
387
|
+
);
|
|
388
|
+
|
|
389
|
+
await this.orderCert(statusPageDomain);
|
|
390
|
+
}
|
|
391
|
+
|
|
251
392
|
@CaptureSpan()
|
|
252
393
|
public async updateSslProvisioningStatusForAllDomains(): Promise<void> {
|
|
253
394
|
const domains: Array<StatusPageDomain> = await this.findBy({
|
|
@@ -257,6 +398,7 @@ export class Service extends DatabaseService<StatusPageDomain> {
|
|
|
257
398
|
},
|
|
258
399
|
select: {
|
|
259
400
|
_id: true,
|
|
401
|
+
fullDomain: true,
|
|
260
402
|
},
|
|
261
403
|
limit: LIMIT_MAX,
|
|
262
404
|
skip: 0,
|
|
@@ -265,9 +407,27 @@ export class Service extends DatabaseService<StatusPageDomain> {
|
|
|
265
407
|
},
|
|
266
408
|
});
|
|
267
409
|
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
410
|
+
/*
|
|
411
|
+
* Each domain costs a request out to the customer's status page, so walking
|
|
412
|
+
* the fleet one at a time makes the sweep as long as the fleet is slow.
|
|
413
|
+
* That length is the delay before an expired certificate is noticed and
|
|
414
|
+
* reordered, so it is the outage a customer sees when renewal has not
|
|
415
|
+
* already happened - it must stay well inside the sweep's own interval.
|
|
416
|
+
*/
|
|
417
|
+
await ArrayUtil.forEachWithConcurrency(
|
|
418
|
+
domains,
|
|
419
|
+
Service.SSL_PROVISIONING_CHECK_CONCURRENCY,
|
|
420
|
+
async (domain: StatusPageDomain): Promise<void> => {
|
|
421
|
+
try {
|
|
422
|
+
await this.updateSslProvisioningStatus(domain);
|
|
423
|
+
} catch (err) {
|
|
424
|
+
// one unreachable domain must not end the sweep for the rest.
|
|
425
|
+
logger.error(err, {
|
|
426
|
+
fullDomain: domain.fullDomain,
|
|
427
|
+
} as LogAttributes);
|
|
428
|
+
}
|
|
429
|
+
},
|
|
430
|
+
);
|
|
271
431
|
}
|
|
272
432
|
|
|
273
433
|
private async isSSLProvisioned(
|