@oneuptime/common 14.0.13 → 14.0.14
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/AlertGroupingRule.ts +10 -6
- package/Models/DatabaseModels/File.ts +41 -2
- package/Models/DatabaseModels/Form.ts +126 -0
- package/Models/DatabaseModels/IncidentGroupingRule.ts +10 -6
- package/Models/DatabaseModels/LogDropFilter.ts +1 -0
- package/Models/DatabaseModels/LogPipeline.ts +1 -0
- package/Models/DatabaseModels/LogScrubRule.ts +14 -8
- package/Models/DatabaseModels/MetricRecordingRule.ts +2 -1
- package/Models/DatabaseModels/OnCallDutyPolicyExecutionLogTimeline.ts +4 -2
- package/Models/DatabaseModels/OnCallDutyPolicyUserOverride.ts +22 -9
- package/Models/DatabaseModels/ProjectCallSMSConfig.ts +6 -1
- package/Models/DatabaseModels/StatusPage.ts +8 -4
- package/Models/DatabaseModels/TraceDropFilter.ts +1 -0
- package/Models/DatabaseModels/TracePipeline.ts +1 -0
- package/Models/DatabaseModels/TraceRecordingRule.ts +2 -1
- package/Models/DatabaseModels/TraceScrubRule.ts +14 -8
- package/Models/DatabaseModels/UserOnCallLog.ts +4 -2
- package/Server/API/CustomDomainRoutes.ts +251 -0
- package/Server/API/DashboardAPI.ts +33 -4
- package/Server/API/DashboardDomainAPI.ts +63 -93
- package/Server/API/StatusPageAPI.ts +92 -0
- package/Server/API/StatusPageDomainAPI.ts +59 -96
- package/Server/Infrastructure/GlobalCache.ts +84 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1797700000000-AddFormBranding.ts +47 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +2 -0
- package/Server/Services/AlertGroupingEngineService.ts +48 -70
- package/Server/Services/AlertGroupingRuleService.ts +38 -0
- package/Server/Services/CephClusterService.ts +25 -0
- package/Server/Services/CloudResourceService.ts +42 -0
- package/Server/Services/DashboardDomainService.ts +640 -214
- package/Server/Services/DashboardService.ts +30 -8
- package/Server/Services/DatabaseService.ts +143 -12
- package/Server/Services/DockerHostService.ts +60 -0
- package/Server/Services/DockerSwarmClusterService.ts +25 -0
- package/Server/Services/FileService.ts +60 -0
- package/Server/Services/FormService.ts +212 -2
- package/Server/Services/GlobalOidcService.ts +10 -0
- package/Server/Services/GlobalSsoService.ts +10 -0
- package/Server/Services/HostService.ts +58 -0
- package/Server/Services/IncidentGroupingEngineService.ts +48 -70
- package/Server/Services/IncidentGroupingRuleService.ts +38 -0
- package/Server/Services/IoTFleetService.ts +26 -0
- package/Server/Services/KubernetesClusterService.ts +64 -0
- package/Server/Services/LabelService.ts +6 -17
- package/Server/Services/LogScrubRuleService.ts +50 -0
- package/Server/Services/OnCallDutyPolicyScheduleService.ts +264 -0
- package/Server/Services/OnCallDutyPolicyUserOverrideService.ts +9 -1
- package/Server/Services/OnCallNotificationAlertingService.ts +24 -29
- package/Server/Services/OnCallSetupReminderService.ts +41 -40
- package/Server/Services/PodmanHostService.ts +60 -0
- package/Server/Services/ProfileAggregationService.ts +38 -0
- package/Server/Services/ProjectCallSMSConfigService.ts +76 -3
- package/Server/Services/ProjectOidcService.ts +20 -0
- package/Server/Services/ProjectSsoService.ts +20 -0
- package/Server/Services/ProxmoxClusterService.ts +25 -0
- package/Server/Services/RumApplicationService.ts +45 -0
- package/Server/Services/ScheduledMaintenanceService.ts +9 -23
- package/Server/Services/ServerlessFunctionService.ts +47 -0
- package/Server/Services/ServiceService.ts +33 -10
- package/Server/Services/StatusPageDomainService.ts +622 -213
- package/Server/Services/StatusPageOidcService.ts +20 -0
- package/Server/Services/StatusPageResourceService.ts +89 -34
- package/Server/Services/StatusPageService.ts +270 -54
- package/Server/Services/StatusPageSsoService.ts +20 -0
- package/Server/Services/TraceScrubRuleService.ts +50 -0
- package/Server/Services/UserIncomingCallNumberService.ts +28 -14
- package/Server/Services/VMwareVCenterService.ts +25 -0
- package/Server/Utils/AI/PerfEvidence/SpanTreeAnalyzer.ts +3 -3
- package/Server/Utils/Greenlock/CertificateOrder.ts +482 -0
- package/Server/Utils/Greenlock/CertificateOrderBudget.ts +134 -0
- package/Server/Utils/Greenlock/CertificateOrderFailures.ts +288 -0
- package/Server/Utils/Greenlock/CertificateOrderLock.ts +163 -0
- package/Server/Utils/Greenlock/CertificateOrderOutcome.ts +29 -0
- package/Server/Utils/Greenlock/CertificateOwners.ts +72 -0
- package/Server/Utils/Greenlock/CertificateReissueOrder.ts +99 -0
- package/Server/Utils/Greenlock/CustomDomainOrders.ts +397 -0
- package/Server/Utils/Greenlock/Greenlock.ts +839 -203
- package/Server/Utils/Rules/GroupingRuleEpisodeOwners.ts +551 -0
- package/Server/Utils/Rules/OwnerRuleAssignment.ts +8 -1
- package/Server/Utils/ScrubRuleValidation.ts +248 -0
- package/Server/Utils/StatusPage/AffectedStatusPageResources.ts +138 -0
- package/Server/Utils/StatusPage/StatusPagesListingMonitorsBuilder.ts +294 -0
- package/Server/Utils/Telemetry/DiscoveredResourceCreate.ts +275 -0
- package/Server/Utils/Telemetry/DiscoveredResourceUpdate.ts +217 -0
- package/Server/Utils/Telemetry/MessageQueueDiscovery.ts +8 -2
- package/Tests/App/Accounts/FormPage.test.tsx +238 -0
- package/Tests/App/Accounts/FormUtils.test.ts +108 -0
- package/Tests/App/AdminDashboard/AdminAddToProjectMembersTeam.test.tsx +1087 -0
- package/Tests/App/AdminDashboard/AdminAuthenticationRequireSso.test.tsx +140 -138
- package/Tests/App/AdminDashboard/AdminAuthenticationSsoCardLocales.test.tsx +144 -145
- package/Tests/App/AdminDashboard/AdminSettingsFormsOnePage.test.tsx +907 -0
- package/Tests/App/AdminDashboard/AdminSettingsSwitches.test.tsx +906 -0
- package/Tests/App/AdminDashboard/AdminSmtpSettingsForm.test.tsx +823 -0
- package/Tests/App/AdminDashboard/BulkAddUsersToProjectModal.test.tsx +341 -368
- package/Tests/App/AdminDashboard/GlobalSsoOidcPages.test.tsx +199 -54
- package/Tests/App/AdminDashboard/ProjectScopedTeamsPicker.test.tsx +991 -0
- package/Tests/App/Dashboard/AIInvestigationSettingsLimits.test.tsx +147 -90
- package/Tests/App/Dashboard/AdminNotificationRulesPage.test.tsx +224 -104
- package/Tests/App/Dashboard/AdminUserNotificationMethodsPage.test.tsx +302 -0
- package/Tests/App/Dashboard/AdminUserOnCallPages.test.tsx +408 -152
- package/Tests/App/Dashboard/AffectedResourcesPicker.test.tsx +55 -0
- package/Tests/App/Dashboard/AffectedResourcesPickerEditForm.test.tsx +206 -115
- package/Tests/App/Dashboard/AffectedResourcesPickerFocusLeave.test.tsx +32 -0
- package/Tests/App/Dashboard/AffectedResourcesSummaryStep.test.tsx +206 -71
- package/Tests/App/Dashboard/AlertEpisodeViewFields.test.tsx +45 -9
- package/Tests/App/Dashboard/AnnouncementCreateForm.test.tsx +1208 -0
- package/Tests/App/Dashboard/AnnouncementEditAndTemplateForms.test.tsx +693 -0
- package/Tests/App/Dashboard/AnnouncementFormsStructure.test.ts +546 -0
- package/Tests/App/Dashboard/AnnouncementStatusPageSuggestions.test.tsx +425 -0
- package/Tests/App/Dashboard/AnnouncementsTableCreateLinks.test.tsx +267 -0
- package/Tests/App/Dashboard/ApiKeyCreateForm.test.ts +68 -51
- package/Tests/App/Dashboard/ApiKeyViewPermissions.test.tsx +11 -9
- package/Tests/App/Dashboard/ApiKeysCreateAccess.test.tsx +24 -16
- package/Tests/App/Dashboard/BulkChangeStateModalOnePage.test.tsx +333 -0
- package/Tests/App/Dashboard/CardDescriptionsSayWhatFor.test.tsx +307 -0
- package/Tests/App/Dashboard/ChangeAlertStateAIHeader.test.tsx +18 -4
- package/Tests/App/Dashboard/CloudDocumentationCard.test.tsx +7 -2
- package/Tests/App/Dashboard/ColorFieldsPrefilledPages.test.tsx +453 -0
- package/Tests/App/Dashboard/CreateFromRecordBreadcrumbs.test.ts +272 -0
- package/Tests/App/Dashboard/CreateFromRecordLinks.test.tsx +495 -0
- package/Tests/App/Dashboard/CreateFromRecordPages.test.tsx +1026 -0
- package/Tests/App/Dashboard/CreateWorkflowModal.test.tsx +65 -23
- package/Tests/App/Dashboard/CriteriaName.test.ts +5 -1
- package/Tests/App/Dashboard/CustomDomainCreateFlow.test.tsx +516 -0
- package/Tests/App/Dashboard/CustomDomainDnsSetupModal.test.tsx +547 -0
- package/Tests/App/Dashboard/CustomDomainsPages.test.tsx +1077 -0
- package/Tests/App/Dashboard/CustomFieldSimpleCreate.test.tsx +2 -2
- package/Tests/App/Dashboard/CustomFieldSimpleCreateRender.test.tsx +12 -6
- package/Tests/App/Dashboard/CustomFieldsSettingsIncidentOptions.test.tsx +1 -1
- package/Tests/App/Dashboard/CustomSmtpConfigForm.test.tsx +969 -0
- package/Tests/App/Dashboard/DashboardBlankCanvasAddWidget.test.tsx +425 -0
- package/Tests/App/Dashboard/DashboardCommandPalette.test.tsx +400 -0
- package/Tests/App/Dashboard/DashboardComponentsMRTranslation.test.tsx +4 -3
- package/Tests/App/Dashboard/DashboardCreateForm.test.ts +375 -0
- package/Tests/App/Dashboard/DashboardCreateFromTemplate.test.tsx +727 -0
- package/Tests/App/Dashboard/DashboardEmptyCanvasAddWidget.test.tsx +86 -0
- package/Tests/App/Dashboard/DashboardPhoneProductsMenu.test.tsx +99 -9
- package/Tests/App/Dashboard/DashboardSharingCard.test.tsx +1226 -0
- package/Tests/App/Dashboard/DashboardSharingEntryPoints.test.tsx +383 -0
- package/Tests/App/Dashboard/DashboardSharingPage.test.tsx +478 -0
- package/Tests/App/Dashboard/DeclareFormsAdvancedRender.test.tsx +90 -34
- package/Tests/App/Dashboard/DeclareIncidentMonitorsApart.test.tsx +1028 -0
- package/Tests/App/Dashboard/DefaultSsoTeams.test.tsx +215 -0
- package/Tests/App/Dashboard/DisabledWarningArchived.test.tsx +3 -3
- package/Tests/App/Dashboard/DisabledWarningRobustness.test.tsx +15 -12
- package/Tests/App/Dashboard/DiscoveredResourceCreateForms.test.tsx +936 -0
- package/Tests/App/Dashboard/EmbeddedMetricCardGroup.test.tsx +720 -0
- package/Tests/App/Dashboard/EpisodeMemberRoleAssignmentsFormField.test.tsx +331 -0
- package/Tests/App/Dashboard/EpisodePostmortemPage.test.tsx +327 -0
- package/Tests/App/Dashboard/EscalationRuleForm.test.ts +2 -2
- package/Tests/App/Dashboard/EscalationRuleFormGuard.test.ts +6 -2
- package/Tests/App/Dashboard/EscalationRuleOneStep.test.tsx +8 -4
- package/Tests/App/Dashboard/EventMeasurements.test.ts +1175 -0
- package/Tests/App/Dashboard/EventMeasurementsCard.test.tsx +993 -0
- package/Tests/App/Dashboard/EventNoteComposerDialog.test.tsx +939 -0
- package/Tests/App/Dashboard/EventNotes.test.tsx +34 -1
- package/Tests/App/Dashboard/EventOverviewPages.test.tsx +186 -1
- package/Tests/App/Dashboard/EventSettingsSwitchPages.test.tsx +625 -0
- package/Tests/App/Dashboard/ExceptionMonitorEnvironmentFilter.test.tsx +6 -2
- package/Tests/App/Dashboard/FeedNoteComposerDialog.test.tsx +1327 -0
- package/Tests/App/Dashboard/FeedNoteDialogHelpers.ts +109 -0
- package/Tests/App/Dashboard/FilterChipClearButton.test.tsx +356 -0
- package/Tests/App/Dashboard/FormBrandingSection.test.tsx +504 -0
- package/Tests/App/Dashboard/FormBrandingValues.test.ts +255 -0
- package/Tests/App/Dashboard/FormBuilderParts.test.tsx +38 -1
- package/Tests/App/Dashboard/FormBuilderUi.test.tsx +176 -2
- package/Tests/App/Dashboard/FormMappingCard.test.tsx +33 -13
- package/Tests/App/Dashboard/FormsMovedPagesAndSubmissions.test.tsx +1 -1
- package/Tests/App/Dashboard/GeneratedKeyForms.test.tsx +30 -7
- package/Tests/App/Dashboard/GlobalProbesOnNewMonitorsCard.test.tsx +258 -0
- package/Tests/App/Dashboard/GroupingRuleFormFlow.test.tsx +653 -37
- package/Tests/App/Dashboard/GroupingRulePages.test.tsx +218 -9
- package/Tests/App/Dashboard/IncidentCreateStatusPageScope.test.tsx +52 -4
- package/Tests/App/Dashboard/IncidentEpisodeFeedPublicNoteNotifyDefault.test.tsx +230 -338
- package/Tests/App/Dashboard/IncidentEpisodeViewFields.test.tsx +45 -9
- package/Tests/App/Dashboard/IncidentFeedPublicNoteNotifyDefault.test.tsx +227 -295
- package/Tests/App/Dashboard/IncidentLinkedAlertsSettingsPage.test.tsx +157 -181
- package/Tests/App/Dashboard/IncidentPostmortemPage.test.tsx +775 -0
- package/Tests/App/Dashboard/IncidentRoleFormField.test.tsx +379 -15
- package/Tests/App/Dashboard/IncidentRolesSettingsPage.test.tsx +148 -32
- package/Tests/App/Dashboard/IncidentTemplateInitialState.test.tsx +430 -0
- package/Tests/App/Dashboard/IncidentTemplateMonitorsApart.test.tsx +492 -0
- package/Tests/App/Dashboard/IncomingCallEscalationOneStep.test.tsx +830 -0
- package/Tests/App/Dashboard/IncomingCallEscalationRuleForm.test.ts +510 -0
- package/Tests/App/Dashboard/IncomingCallEscalationRuleFormGuard.test.ts +378 -0
- package/Tests/App/Dashboard/IngestionKeyForm.test.ts +664 -0
- package/Tests/App/Dashboard/IngestionKeySelectorCreate.test.tsx +523 -0
- package/Tests/App/Dashboard/InventoryTypeAndStatusFacets.test.tsx +130 -9
- package/Tests/App/Dashboard/IpAllowlistCopy.test.ts +122 -0
- package/Tests/App/Dashboard/KubernetesClusterAiPage.test.tsx +19 -3
- package/Tests/App/Dashboard/KubernetesMetricsSetupEmptyState.test.tsx +275 -0
- package/Tests/App/Dashboard/KubernetesMetricsSetupHints.test.tsx +720 -0
- package/Tests/App/Dashboard/LabelsFormField.test.tsx +18 -13
- package/Tests/App/Dashboard/LegacyDefaultAssigneeNote.test.tsx +359 -0
- package/Tests/App/Dashboard/LogMonitorAttributeOperatorPreview.test.tsx +10 -10
- package/Tests/App/Dashboard/MarkdownTemplateDialogsWide.test.tsx +42 -20
- package/Tests/App/Dashboard/MeasurementForms.test.tsx +191 -5
- package/Tests/App/Dashboard/MeasurementPagesI18n.test.ts +2 -0
- package/Tests/App/Dashboard/MeasurementSetup.test.ts +5 -2
- package/Tests/App/Dashboard/MenuSpecificFoldedSections.test.tsx +38 -12
- package/Tests/App/Dashboard/MessageQueueRulePages.test.tsx +34 -11
- package/Tests/App/Dashboard/MetricAndRecordingRuleFormsRender.test.tsx +1206 -0
- package/Tests/App/Dashboard/MetricResultsState.test.ts +248 -0
- package/Tests/App/Dashboard/MetricViewResultsState.test.tsx +404 -0
- package/Tests/App/Dashboard/MonitorCreateFromMonitorBackedDevice.test.tsx +1 -1
- package/Tests/App/Dashboard/MonitorCriteriaAdvancedOptions.test.tsx +77 -27
- package/Tests/App/Dashboard/MonitorCriteriaAttributeFilter.test.tsx +5 -8
- package/Tests/App/Dashboard/MonitorCriteriaHeaderControls.test.tsx +228 -0
- package/Tests/App/Dashboard/MonitorCriteriaIncidentRoles.test.tsx +411 -0
- package/Tests/App/Dashboard/MonitorFeedRefresh.test.tsx +5 -1
- package/Tests/App/Dashboard/MonitorFormIncidentRoles.test.tsx +460 -0
- package/Tests/App/Dashboard/MonitorIntervalRedirect.test.tsx +299 -0
- package/Tests/App/Dashboard/MonitorOverviewHero.test.tsx +243 -2
- package/Tests/App/Dashboard/MonitorProbesAndIntervalPage.test.tsx +638 -0
- package/Tests/App/Dashboard/MonitorStepsDefaultStatusAdvanced.test.tsx +2 -2
- package/Tests/App/Dashboard/MonitorSummaryTestMonitorButton.test.tsx +2 -2
- package/Tests/App/Dashboard/MonitoringIntervalCard.test.tsx +493 -0
- package/Tests/App/Dashboard/MonitoringSwitch.test.tsx +597 -0
- package/Tests/App/Dashboard/MovedRunnerSettingsRedirects.test.tsx +4 -5
- package/Tests/App/Dashboard/NotificationChannelOffSwitchLists.test.tsx +636 -0
- package/Tests/App/Dashboard/OnCallPolicyCreateFormGuard.test.ts +8 -4
- package/Tests/App/Dashboard/OnCallPolicyFirstResponders.test.tsx +1 -1
- package/Tests/App/Dashboard/OnCallReadinessSurfaces.test.tsx +54 -0
- package/Tests/App/Dashboard/OnCallRulesDeleteGuard.test.tsx +43 -24
- package/Tests/App/Dashboard/OnCallRulesRedirects.test.tsx +530 -0
- package/Tests/App/Dashboard/OnCallRulesTable.test.tsx +158 -74
- package/Tests/App/Dashboard/OnCallRulesTabs.test.tsx +511 -0
- package/Tests/App/Dashboard/OnCallScheduleAddLayerDefaults.test.tsx +236 -0
- package/Tests/App/Dashboard/OnCallScheduleCreateFormGuard.test.ts +633 -0
- package/Tests/App/Dashboard/OnCallScheduleOverrideClarity.test.tsx +13 -2
- package/Tests/App/Dashboard/OnCallScheduleWhoTakesTurns.test.tsx +771 -0
- package/Tests/App/Dashboard/OnCallSharedCalendarFeedSettingsForm.test.tsx +357 -0
- package/Tests/App/Dashboard/OnCallShiftRemindersAndUpcomingShifts.test.tsx +16 -6
- package/Tests/App/Dashboard/OnboardingSsoEmptyState.test.tsx +112 -23
- package/Tests/App/Dashboard/PageSearchIndexCoversMenus.test.tsx +594 -0
- package/Tests/App/Dashboard/PageSearchIndexCoversRoutes.test.tsx +271 -0
- package/Tests/App/Dashboard/PageSearchRanking.test.tsx +373 -0
- package/Tests/App/Dashboard/PostmortemPageParts.test.tsx +548 -0
- package/Tests/App/Dashboard/ProbeAgreementCard.test.tsx +483 -0
- package/Tests/App/Dashboard/ProductOrientation.test.tsx +9 -2
- package/Tests/App/Dashboard/ProjectAISettingsPages.test.tsx +282 -404
- package/Tests/App/Dashboard/ProjectAiSettingsSwitchPages.test.tsx +1414 -0
- package/Tests/App/Dashboard/ProjectNotificationChannels.test.tsx +1191 -0
- package/Tests/App/Dashboard/ProjectSettingsSwitchCards.test.tsx +603 -0
- package/Tests/App/Dashboard/RemindersCard.test.tsx +477 -0
- package/Tests/App/Dashboard/ResourceDetailsCard.test.tsx +458 -0
- package/Tests/App/Dashboard/ResourceRuleForm.test.ts +525 -0
- package/Tests/App/Dashboard/ResourceRuleFormsRender.test.tsx +803 -0
- package/Tests/App/Dashboard/RoleAccess.test.ts +753 -0
- package/Tests/App/Dashboard/RoleCardSelectOptions.test.ts +13 -6
- package/Tests/App/Dashboard/RouteUtilPageRoute.test.ts +116 -0
- package/Tests/App/Dashboard/RowActionPlacementOverrides.test.tsx +1 -1
- package/Tests/App/Dashboard/RumSessionReplayRetentionSettings.test.tsx +172 -219
- package/Tests/App/Dashboard/RunbookStepHeaderControls.test.tsx +269 -0
- package/Tests/App/Dashboard/RunnerKubernetesAgentForm.test.tsx +45 -85
- package/Tests/App/Dashboard/RunnerSupersededByAiAgentNote.test.tsx +16 -23
- package/Tests/App/Dashboard/ScheduledMaintenanceAffectedResourcesEditForm.test.tsx +485 -0
- package/Tests/App/Dashboard/ScheduledMaintenanceChangeStateNotifyDefault.test.tsx +27 -2
- package/Tests/App/Dashboard/ScheduledMaintenanceCreateForm.test.tsx +65 -28
- package/Tests/App/Dashboard/ScheduledMaintenanceFeedPublicNoteNotifyDefault.test.tsx +208 -309
- package/Tests/App/Dashboard/ScheduledMaintenanceFeedRefresh.test.tsx +36 -53
- package/Tests/App/Dashboard/ScheduledMaintenanceFormsStructure.test.ts +83 -14
- package/Tests/App/Dashboard/ScheduledMaintenanceMonitorsApart.test.tsx +1085 -0
- package/Tests/App/Dashboard/ScheduledMaintenanceOverviewPage.test.tsx +378 -25
- package/Tests/App/Dashboard/ScheduledMaintenanceStatusPageSuggestions.test.tsx +513 -0
- package/Tests/App/Dashboard/ScheduledMaintenanceTemplateForm.test.tsx +31 -9
- package/Tests/App/Dashboard/ScheduledMaintenanceTemplateMonitorsApart.test.tsx +760 -0
- package/Tests/App/Dashboard/SecurityEventConnectionFormModal.test.tsx +11 -13
- package/Tests/App/Dashboard/SecurityEventsMonitorStepForm.test.tsx +228 -69
- package/Tests/App/Dashboard/SelectedProjectSwitches.test.tsx +359 -0
- package/Tests/App/Dashboard/ServerlessSetupGuide.test.ts +1 -1
- package/Tests/App/Dashboard/SessionReplayAllowedCard.test.tsx +297 -0
- package/Tests/App/Dashboard/SetupGuideCard.test.tsx +7 -1
- package/Tests/App/Dashboard/ShortFormsOnePage.test.tsx +591 -0
- package/Tests/App/Dashboard/SloNoticeBanner.test.tsx +253 -6
- package/Tests/App/Dashboard/SloOverviewData.test.tsx +99 -0
- package/Tests/App/Dashboard/SloOverviewLayout.test.tsx +3 -1
- package/Tests/App/Dashboard/SloSettings.test.tsx +257 -4
- package/Tests/App/Dashboard/SsoPages.test.tsx +448 -52
- package/Tests/App/Dashboard/StateChangeDialogsFolded.test.tsx +695 -0
- package/Tests/App/Dashboard/StateChangeFormFields.test.ts +376 -0
- package/Tests/App/Dashboard/StatusPageAccessCard.test.tsx +1088 -0
- package/Tests/App/Dashboard/StatusPageAccessCopy.test.ts +450 -0
- package/Tests/App/Dashboard/StatusPageAccessMenu.test.tsx +137 -0
- package/Tests/App/Dashboard/StatusPageAccessPage.test.tsx +458 -0
- package/Tests/App/Dashboard/StatusPageAdvancedSettingsPage.test.tsx +30 -86
- package/Tests/App/Dashboard/StatusPageBrandingPage.test.tsx +28 -15
- package/Tests/App/Dashboard/StatusPageDisplaySettingsCard.test.tsx +949 -14
- package/Tests/App/Dashboard/StatusPagePrivateUsersNotice.test.tsx +233 -0
- package/Tests/App/Dashboard/StatusPageReportsCard.test.tsx +1001 -0
- package/Tests/App/Dashboard/StatusPageRequireSsoCard.test.tsx +247 -0
- package/Tests/App/Dashboard/StatusPageSubscriberSettingsPages.test.tsx +4 -17
- package/Tests/App/Dashboard/StatusPageSuggestions.test.tsx +930 -0
- package/Tests/App/Dashboard/StatusPageSwitchCardPages.test.tsx +335 -0
- package/Tests/App/Dashboard/TeamBlockPermissionsRedirect.test.tsx +332 -0
- package/Tests/App/Dashboard/TeamCreateForm.test.ts +206 -0
- package/Tests/App/Dashboard/TeamViewPermissions.test.tsx +713 -0
- package/Tests/App/Dashboard/TeamViewSideMenuBlockPermissions.test.tsx +113 -0
- package/Tests/App/Dashboard/TeamsCreateAccess.test.tsx +799 -0
- package/Tests/App/Dashboard/TelemetryDataRuleForms.test.ts +655 -0
- package/Tests/App/Dashboard/TelemetryDataRuleFormsRender.test.tsx +1014 -0
- package/Tests/App/Dashboard/TelemetryIngestionKeyEdit.test.tsx +6 -3
- package/Tests/App/Dashboard/TelemetryIngestionKeyForm.test.tsx +446 -446
- package/Tests/App/Dashboard/TelemetryMonitorFiltersFold.test.tsx +613 -0
- package/Tests/App/Dashboard/TelemetryRetentionShells.test.tsx +37 -2
- package/Tests/App/Dashboard/TemplateFormsNoInternalDataWarning.test.tsx +3 -3
- package/Tests/App/Dashboard/TraceExplorer.test.tsx +338 -0
- package/Tests/App/Dashboard/TwilioConfigFirstDefault.test.tsx +786 -0
- package/Tests/App/Dashboard/UpcomingShiftGetCover.test.tsx +306 -0
- package/Tests/App/Dashboard/UseBulkShortenDeviceNames.test.tsx +36 -11
- package/Tests/App/Dashboard/UserOverrideForm.test.ts +505 -0
- package/Tests/App/Dashboard/UserOverrideFormGuard.test.ts +334 -0
- package/Tests/App/Dashboard/UserOverrideWhoIsAway.test.tsx +999 -0
- package/Tests/App/Dashboard/UserSettingsSetupChecklistModel.test.ts +33 -11
- package/Tests/App/Dashboard/UserSettingsSetupChecklistPage.test.tsx +49 -4
- package/Tests/App/Dashboard/UsersPageEmptyState.test.tsx +245 -0
- package/Tests/App/Dashboard/WorkflowVariableOAuthSettingsEditSteps.test.tsx +13 -6
- package/Tests/App/Dashboard/WorkspaceMenusConnected.test.tsx +0 -2
- package/Tests/App/StatusPage/BulkAddStatusPageMonitorsModal.test.tsx +108 -86
- package/Tests/App/StatusPage/StatusPageResourceExplorer.test.tsx +397 -0
- package/Tests/App/StatusPage/StatusPageResourceForm.test.tsx +931 -0
- package/Tests/App/StatusPage/StatusPageSubscribeOnePage.test.tsx +686 -0
- package/Tests/DialogActionRules.ts +16 -5
- package/Tests/Helpers/CardHeaderScan.ts +258 -0
- package/Tests/Helpers/FormStepsScan.ts +576 -11
- package/Tests/Helpers/MonitorGroupStatusPageRows.ts +237 -0
- package/Tests/Helpers/NestedControls.ts +184 -0
- package/Tests/Helpers/NestedControlsScan.ts +414 -0
- package/Tests/Helpers/SteppedFooterScan.ts +722 -0
- package/Tests/Models/DatabaseModels/FormModel.test.ts +31 -7
- package/Tests/Models/DatabaseModels/UserOverrideColumnDescriptions.test.ts +123 -0
- package/Tests/Models/TelemetryDataRuleColumnDefaults.test.ts +239 -0
- package/Tests/ResponsiveFlexLayout.test.ts +111 -0
- package/Tests/ResponsiveFlexLayout.ts +165 -0
- package/Tests/Server/API/DashboardDomainOrderSslAPI.test.ts +372 -0
- package/Tests/Server/API/DashboardDomainVerifyCnameAPI.test.ts +921 -0
- package/Tests/Server/API/DashboardSharingPublicRoutes.test.ts +559 -0
- package/Tests/Server/API/FormBrandingPublicRoutes.test.ts +680 -0
- package/Tests/Server/API/ProjectAPICreateWithTenantHeader.test.ts +300 -0
- package/Tests/Server/API/ProjectCreateTestHelpers.ts +211 -0
- package/Tests/Server/API/ProjectCreateWithTenantHeaderPostgres.test.ts +387 -0
- package/Tests/Server/API/PublicRouteInvalidAccessToken.test.ts +29 -12
- package/Tests/Server/API/StatusPageDomainVerifyCnameAPI.test.ts +1090 -0
- package/Tests/Server/API/StatusPageMasterPageAccess.test.ts +254 -0
- package/Tests/Server/API/StatusPageReportScheduleWrites.test.ts +829 -0
- package/Tests/Server/API/StatusPageUptimeSettingsWrites.test.ts +417 -0
- package/Tests/Server/API/StatusPagesListingMonitorsAPI.test.ts +1029 -0
- package/Tests/Server/API/StatusPagesListingMonitorsRoute.test.ts +286 -0
- package/Tests/Server/Infrastructure/GlobalCache.test.ts +156 -0
- package/Tests/Server/Infrastructure/Postgres/MigrateIncidentFormsToFormsMigration.test.ts +52 -1
- package/Tests/Server/Services/CustomDomainCertificateLifecycle.test.ts +1559 -0
- package/Tests/Server/Services/CustomDomainCertificateReissue.test.ts +186 -16
- package/Tests/Server/Services/DashboardAccessChoice.test.ts +657 -0
- package/Tests/Server/Services/DashboardCreateFromTemplate.test.ts +200 -0
- package/Tests/Server/Services/DashboardDomainCertificateSweeps.test.ts +1142 -0
- package/Tests/Server/Services/DiscoveredResourceCreate.test.ts +864 -0
- package/Tests/Server/Services/DiscoveredResourceUpdate.test.ts +822 -0
- package/Tests/Server/Services/EpisodeRuleSeverityRepair.test.ts +3 -4
- package/Tests/Server/Services/FileServiceProject.test.ts +345 -0
- package/Tests/Server/Services/FormBranding.test.ts +982 -0
- package/Tests/Server/Services/FormPublicForm.test.ts +15 -0
- package/Tests/Server/Services/GroupingRuleEpisodeOwners.test.ts +857 -0
- package/Tests/Server/Services/IncidentFormPostgres.test.ts +297 -1
- package/Tests/Server/Services/MachinePickedColors.test.ts +202 -0
- package/Tests/Server/Services/OidcProviderCreateDefaults.test.ts +252 -0
- package/Tests/Server/Services/OnCallDutyPolicyScheduleFirstLayer.test.ts +799 -0
- package/Tests/Server/Services/OnCallDutyPolicyScheduleFirstLayerPlans.test.ts +172 -0
- package/Tests/Server/Services/OnCallDutyPolicyUserOverrideWhoIsAway.test.ts +571 -0
- package/Tests/Server/Services/OnCallSetupReminder.test.ts +35 -13
- package/Tests/Server/Services/OnCallUndeliverablePageRulesLink.test.ts +217 -0
- package/Tests/Server/Services/ProfileAggregationService.test.ts +213 -4
- package/Tests/Server/Services/ProjectCallSMSConfigFirstDefault.test.ts +699 -0
- package/Tests/Server/Services/ProjectCallSMSConfigFirstDefaultBilling.test.ts +247 -0
- package/Tests/Server/Services/SamlProviderCreateDefaults.test.ts +255 -0
- package/Tests/Server/Services/ScheduledMaintenanceSubscriberMonitorGroups.test.ts +333 -0
- package/Tests/Server/Services/ScrubRuleSaveValidation.test.ts +947 -0
- package/Tests/Server/Services/StaticRuleCriteriaRuntimeCoverage.test.ts +17 -4
- package/Tests/Server/Services/StatusPageAccessChoice.test.ts +548 -0
- package/Tests/Server/Services/StatusPageDomainCertificateSweeps.test.ts +1238 -0
- package/Tests/Server/Services/TeamCreateAccessGrant.test.ts +607 -0
- package/Tests/Server/Services/TwilioConfigSendersGuard.test.ts +249 -0
- package/Tests/Server/Services/VerificationCodesUseProjectTwilioConfig.test.ts +264 -0
- package/Tests/Server/Types/Database/Permissions/FormBrandingColumns.test.ts +270 -0
- package/Tests/Server/Utils/Greenlock/CertificateCleanup.test.ts +526 -0
- package/Tests/Server/Utils/Greenlock/CertificateOrder.test.ts +1062 -0
- package/Tests/Server/Utils/Greenlock/CertificateOrderBudget.test.ts +243 -0
- package/Tests/Server/Utils/Greenlock/CertificateOrderFailures.test.ts +293 -0
- package/Tests/Server/Utils/Greenlock/CertificateOrderLock.test.ts +152 -0
- package/Tests/Server/Utils/Greenlock/CertificateOwnersGuard.test.ts +119 -0
- package/Tests/Server/Utils/Greenlock/CertificateRenewalOwnership.test.ts +1170 -0
- package/Tests/Server/Utils/Greenlock/CertificateRenewalSafety.test.ts +368 -0
- package/Tests/Server/Utils/Greenlock/CertificateRenewalSchedule.test.ts +188 -11
- package/Tests/Server/Utils/Greenlock/CustomDomainOrders.test.ts +723 -0
- package/Tests/Server/Utils/Greenlock/InMemoryRedis.ts +189 -0
- package/Tests/Server/Utils/Greenlock/NginxAcmeCertificatesToDisk.test.ts +242 -0
- package/Tests/Server/Utils/Greenlock/NginxCustomCertificatesToDisk.test.ts +305 -0
- package/Tests/Server/Utils/Greenlock/OrderCertGuards.test.ts +583 -0
- package/Tests/Server/Utils/Greenlock/OrderCertStorage.test.ts +203 -0
- package/Tests/Server/Utils/StatusPage/AffectedStatusPageResources.test.ts +700 -0
- package/Tests/Server/Utils/StatusPage/StatusPagesListingMonitorsBuilder.test.ts +744 -0
- package/Tests/Types/CustomDomain/CustomDomainCertificates.test.ts +106 -0
- package/Tests/Types/CustomDomain/CustomDomainVerification.test.ts +94 -0
- package/Tests/Types/Dashboard/DashboardAccess.test.ts +460 -0
- package/Tests/Types/Filter/FilterConditionUtil.test.ts +59 -0
- package/Tests/Types/Form/FormBranding.test.ts +760 -0
- package/Tests/Types/IncomingCall/IncomingCallRingTime.test.ts +80 -0
- package/Tests/Types/NotificationRule/OnCallRuleKind.test.ts +271 -0
- package/Tests/Types/OnCallDutyPolicy/ScheduleFirstLayer.test.ts +300 -0
- package/Tests/Types/OnCallDutyPolicy/ScheduleLayerDefaults.test.ts +316 -0
- package/Tests/Types/OnCallDutyPolicy/UserOverrideCoverRequest.test.ts +257 -0
- package/Tests/Types/SSO/OidcProviderDefaults.test.ts +474 -0
- package/Tests/Types/SSO/SamlProviderDefaults.test.ts +150 -0
- package/Tests/Types/SSO/SsoProviderDefaults.test.ts +181 -0
- package/Tests/Types/StatusPage/StatusPageAccess.test.ts +393 -0
- package/Tests/Types/StatusPage/StatusPagesListingMonitors.test.ts +149 -0
- package/Tests/Types/Telemetry/ScrubRule.test.ts +375 -0
- package/Tests/UI/Components/AdvancedPageSection.test.tsx +201 -61
- package/Tests/UI/Components/BasicFormModalSteps.test.tsx +129 -153
- package/Tests/UI/Components/Card.test.tsx +354 -367
- package/Tests/UI/Components/CardHeaderActionsGuard.test.tsx +605 -0
- package/Tests/UI/Components/CardModelDetailHeaderLayout.test.tsx +23 -8
- package/Tests/UI/Components/CardModelDetailOnBeforeUpdate.test.tsx +224 -0
- package/Tests/UI/Components/CardModelDetailPageButtons.test.tsx +231 -0
- package/Tests/UI/Components/ChoiceRows.test.tsx +365 -0
- package/Tests/UI/Components/CommandPalette/CommandPalette.test.tsx +341 -5
- package/Tests/UI/Components/CommandPalette/PaletteFilter.test.ts +655 -64
- package/Tests/UI/Components/Detail/DetailCreatedOnIdLine.test.tsx +669 -0
- package/Tests/UI/Components/Detail/DetailIdLineDarkMode.test.ts +34 -7
- package/Tests/UI/Components/Detail/DetailIdLineInLocale.test.tsx +71 -0
- package/Tests/UI/Components/Detail/DetailRecordIdLine.test.tsx +26 -7
- package/Tests/UI/Components/Detail/DetailRecordLine.test.tsx +326 -0
- package/Tests/UI/Components/Detail/DetailRecordTime.test.ts +324 -0
- package/Tests/UI/Components/DetailCompactStyle.test.tsx +7 -3
- package/Tests/UI/Components/Dropdown/DropdownChange.test.ts +163 -0
- package/Tests/UI/Components/EntityDropdown.test.tsx +103 -1
- package/Tests/UI/Components/EntityDropdownClearButton.test.tsx +638 -0
- package/Tests/UI/Components/EntityDropdownEscape.test.tsx +6 -6
- package/Tests/UI/Components/EntityDropdownFocusLeave.test.tsx +21 -4
- package/Tests/UI/Components/EntityDropdownQuery.test.tsx +411 -0
- package/Tests/UI/Components/EntityDropdownQueryHelpers.test.ts +131 -0
- package/Tests/UI/Components/FilePicker.test.tsx +220 -1
- package/Tests/UI/Components/FoldedSection/FoldedSection.test.tsx +582 -0
- package/Tests/UI/Components/FoldedSection/FoldedSectionDarkMode.test.ts +197 -0
- package/Tests/UI/Components/FoldedSection/FoldedSectionItem.test.ts +247 -0
- package/Tests/UI/Components/FoldedSection/FoldedSectionQueries.ts +86 -0
- package/Tests/UI/Components/Forms/AdvancedStepsGuard.test.ts +358 -32
- package/Tests/UI/Components/Forms/AnchoredFieldPopupPlacement.test.tsx +195 -0
- package/Tests/UI/Components/Forms/BasicFormCollapsibleSections.test.tsx +187 -23
- package/Tests/UI/Components/Forms/BasicFormFillsInOnShow.test.tsx +246 -0
- package/Tests/UI/Components/Forms/BasicFormFooterSetValue.test.tsx +283 -0
- package/Tests/UI/Components/Forms/BasicFormPrimaryActionLastStep.test.tsx +780 -0
- package/Tests/UI/Components/Forms/BasicFormSingleStep.test.tsx +232 -0
- package/Tests/UI/Components/Forms/BasicFormStepValidation.test.tsx +7 -4
- package/Tests/UI/Components/Forms/BasicFormSubmitAllSteps.test.tsx +4 -3
- package/Tests/UI/Components/Forms/CreateFormDefaultsGuard.test.ts +252 -7
- package/Tests/UI/Components/Forms/DeclareAndCreateFormsGuard.test.ts +247 -7
- package/Tests/UI/Components/Forms/DiscoveredResourceCreateFormsGuard.test.ts +492 -0
- package/Tests/UI/Components/Forms/FilterConditionOnlyWithTwoFiltersGuard.test.ts +333 -0
- package/Tests/UI/Components/Forms/FoldedEditorWidthTiming.test.tsx +127 -0
- package/Tests/UI/Components/Forms/FoldedSectionsGuard.test.ts +523 -0
- package/Tests/UI/Components/Forms/FollowPickName.test.ts +88 -0
- package/Tests/UI/Components/Forms/FormFieldDropdownChange.test.tsx +294 -0
- package/Tests/UI/Components/Forms/FormModalWidth.test.tsx +237 -2
- package/Tests/UI/Components/Forms/FormSummary.test.tsx +181 -0
- package/Tests/UI/Components/Forms/IncidentEpisodePublicNoteNotifyPayload.test.tsx +110 -86
- package/Tests/UI/Components/Forms/LabelsFormFieldGuard.test.ts +101 -96
- package/Tests/UI/Components/Forms/LongFormStepsGuard.test.ts +559 -10
- package/Tests/UI/Components/Forms/MarkdownFormsAreWide.test.ts +56 -4
- package/Tests/UI/Components/Forms/MetricAndRecordingRuleFormsGuard.test.ts +400 -0
- package/Tests/UI/Components/Forms/ModelFormColorDefaults.test.tsx +659 -0
- package/Tests/UI/Components/Forms/ModelFormCreateDefaults.test.tsx +108 -4
- package/Tests/UI/Components/Forms/ModelFormDropdownQuery.test.tsx +403 -0
- package/Tests/UI/Components/Forms/ModelFormPreservesUserInput.test.tsx +126 -0
- package/Tests/UI/Components/Forms/ModelFormSinglePickPeoplePicker.test.tsx +453 -0
- package/Tests/UI/Components/Forms/OidcProviderFormsGuard.test.ts +321 -0
- package/Tests/UI/Components/Forms/OneIncidentRolePickerGuard.test.ts +823 -0
- package/Tests/UI/Components/Forms/OneSwitchCardsGuard.test.ts +739 -0
- package/Tests/UI/Components/Forms/OpenFormSections.test.tsx +169 -0
- package/Tests/UI/Components/Forms/OverloadedFormStepsGuard.test.ts +21 -9
- package/Tests/UI/Components/Forms/PrimaryActionLastStepGuard.test.ts +478 -0
- package/Tests/UI/Components/Forms/ProjectTeamFormsGuard.test.ts +240 -0
- package/Tests/UI/Components/Forms/ResourceDetailsOnePlaceGuard.test.ts +936 -0
- package/Tests/UI/Components/Forms/ResourceRuleFormsGuard.test.ts +527 -0
- package/Tests/UI/Components/Forms/SamlProviderFormsGuard.test.ts +387 -0
- package/Tests/UI/Components/Forms/SmallWizardsOnePageGuard.test.ts +331 -0
- package/Tests/UI/Components/Forms/SmtpConfigFormsGuard.test.ts +470 -0
- package/Tests/UI/Components/Forms/StateChangeDialogsFoldTheNote.test.ts +322 -0
- package/Tests/UI/Components/Forms/StatusPageResourceFormsGuard.test.ts +381 -0
- package/Tests/UI/Components/Forms/SteppedFormFooter.test.ts +225 -0
- package/Tests/UI/Components/Forms/SteppedFormFooterTiming.test.tsx +82 -40
- package/Tests/UI/Components/Forms/SwitchCardsGuard.test.ts +339 -0
- package/Tests/UI/Components/Forms/TelemetryDataRuleFormsGuard.test.ts +383 -0
- package/Tests/UI/Components/Forms/UniqueName.test.ts +163 -0
- package/Tests/UI/Components/Forms/Utils/AdvancedFormSection.test.ts +131 -11
- package/Tests/UI/Components/Forms/Utils/CreateFormColorDefaults.test.ts +373 -0
- package/Tests/UI/Components/Forms/Utils/FoldedFormFields.test.ts +482 -0
- package/Tests/UI/Components/LabelRuleImportExport.test.tsx +32 -0
- package/Tests/UI/Components/MemberRoleAssignment.test.tsx +51 -7
- package/Tests/UI/Components/ModalSecondaryButton.test.tsx +60 -3
- package/Tests/UI/Components/ModelFormDraftValues.test.tsx +255 -0
- package/Tests/UI/Components/ModelPageHeaderChanged.test.tsx +293 -0
- package/Tests/UI/Components/ModelSwitchCard.test.tsx +813 -0
- package/Tests/UI/Components/ModelSwitchEvents.test.ts +188 -0
- package/Tests/UI/Components/ModelSwitchRow.test.tsx +861 -0
- package/Tests/UI/Components/ModelSwitchUtil.test.ts +239 -0
- package/Tests/UI/Components/ModelSwitchesCard.test.tsx +699 -0
- package/Tests/UI/Components/NavBar.test.tsx +41 -2
- package/Tests/UI/Components/NavBarCategoryToggleDarkMode.test.ts +12 -0
- package/Tests/UI/Components/NavBarMenuCatalog.test.tsx +197 -30
- package/Tests/UI/Components/NavBarMenuFolding.test.tsx +221 -39
- package/Tests/UI/Components/NavBarMenuSearch.test.tsx +15 -10
- package/Tests/UI/Components/NestedControlsGuard.test.ts +300 -0
- package/Tests/UI/Components/PageBreadcrumbOverride.test.tsx +202 -0
- package/Tests/UI/Components/PeoplePicker/OwnersFieldGuard.test.ts +269 -5
- package/Tests/UI/Components/PeoplePicker/PeoplePickerChange.test.tsx +414 -0
- package/Tests/UI/Components/PeoplePicker/PeoplePickerExcludePicks.test.tsx +582 -0
- package/Tests/UI/Components/PeoplePicker/PeoplePickerSinglePick.test.tsx +519 -0
- package/Tests/UI/Components/PeoplePicker/PeoplePickerSinglePickTypes.test.ts +174 -0
- package/Tests/UI/Components/RuleCriteria/RuleCriteriaModelTable.test.tsx +8 -3
- package/Tests/UI/Components/RuleCriteria/RuleCriteriaNamesGuard.test.ts +14 -6
- package/Tests/UI/Components/RuleRun/RuleViewDescription.test.tsx +107 -0
- package/Tests/UI/Components/SaveStatus.test.tsx +81 -0
- package/Tests/UI/Components/SmtpConfig/SmtpConfigFormFields.test.ts +1078 -0
- package/Tests/UI/Components/Sso/OidcProviderForm.test.tsx +608 -0
- package/Tests/UI/Components/Sso/OidcProviderFormFields.test.ts +698 -0
- package/Tests/UI/Components/Sso/SamlProviderForm.test.tsx +583 -0
- package/Tests/UI/Components/Sso/SamlProviderFormFields.test.ts +619 -0
- package/Tests/UI/Components/SteppedEditFormSave.test.tsx +199 -141
- package/Tests/UI/Components/Table/TableEmptyStateComponent.test.tsx +143 -0
- package/Tests/UI/Components/UseSaveModelSwitch.test.tsx +409 -0
- package/Tests/UI/Components/Workflow/ArgumentsForm.test.tsx +3 -3
- package/Tests/UI/Components/Workflow/ArgumentsFormAdvancedSettings.test.tsx +83 -27
- package/Tests/UI/Components/Workflow/WorkflowLogModal.test.tsx +7 -2
- package/Tests/UI/Components/useSaveOnChange.test.tsx +341 -0
- package/Tests/UI/Monitor/MonitorStepRetrySettings.test.tsx +1 -1
- package/Tests/UI/Rum/ReplayTimeline.test.tsx +75 -5
- package/Tests/UI/Rum/SessionReplaySettingsPolicyLoading.test.tsx +97 -0
- package/Tests/UI/Utils/Breadcrumb/fixtures/RealBreadcrumbTrails.ts +12 -39
- package/Tests/UI/Utils/Breadcrumb/fixtures/RealRoutePatterns.ts +1 -6
- package/Tests/{App/Dashboard → UI/Utils}/DefaultInviteTeam.test.ts +126 -4
- package/Tests/UI/Utils/GrantablePermission.test.ts +172 -0
- package/Tests/UI/Utils/PermissionGateColumnUpdate.test.ts +211 -0
- package/Tests/UI/Utils/TranslateTemplate.test.ts +31 -0
- package/Tests/Utils/DistinctColor.test.ts +446 -0
- package/Tests/Utils/Monitor/MonitorOverviewPresentationUtil.test.ts +14 -2
- package/Tests/Utils/Monitor/MonitoringIntervalUtil.test.ts +1 -1
- package/Tests/Utils/NetworkDiscovery/ShortHostnameUtil.test.ts +2 -2
- package/Tests/Utils/Slo/SloHealth.test.ts +28 -6
- package/Tests/Utils/StatusPage/ReportSchedule.test.ts +867 -0
- package/Tests/Utils/Telemetry/DiscoveredResourceName.test.ts +189 -0
- package/Tests/Utils/WordMatch.test.ts +104 -0
- package/Types/BrandColors.ts +10 -0
- package/Types/CustomDomain/CustomDomainCertificates.ts +128 -0
- package/Types/CustomDomain/CustomDomainVerification.ts +78 -0
- package/Types/Dashboard/DashboardAccess.ts +250 -0
- package/Types/Dashboard/DashboardTemplates.ts +33 -0
- package/Types/Filter/FilterConditionUtil.ts +29 -0
- package/Types/Form/FormBranding.ts +475 -0
- package/Types/Form/FormPublic.ts +26 -0
- package/Types/IncomingCall/IncomingCallRingTime.ts +48 -0
- package/Types/Log/LogScrubField.ts +14 -0
- package/Types/Monitor/SeriesContext/SeriesLabelDisplay.ts +1 -1
- package/Types/NotificationRule/OnCallRuleKind.ts +194 -0
- package/Types/OnCallDutyPolicy/FirstResponders.ts +3 -32
- package/Types/OnCallDutyPolicy/MiscDataId.ts +38 -0
- package/Types/OnCallDutyPolicy/ScheduleFirstLayer.ts +165 -0
- package/Types/OnCallDutyPolicy/ScheduleLayerDefaults.ts +160 -0
- package/Types/OnCallDutyPolicy/UserOverrideCoverRequest.ts +148 -0
- package/Types/SSO/OidcProviderDefaults.ts +282 -0
- package/Types/SSO/SamlProviderDefaults.ts +77 -0
- package/Types/SSO/SsoProviderDefaults.ts +101 -0
- package/Types/StatusPage/StatusPageAccess.ts +215 -0
- package/Types/StatusPage/StatusPagesListingMonitors.ts +150 -0
- package/Types/Telemetry/ScrubRule.ts +240 -0
- package/UI/Components/AdvancedPageSection/AdvancedPageSection.tsx +59 -29
- package/UI/Components/Card/Card.tsx +139 -80
- package/UI/Components/ChoiceRows/ChoiceRows.tsx +249 -0
- package/UI/Components/CommandPalette/CommandPalette.tsx +28 -12
- package/UI/Components/CommandPalette/PaletteFilter.ts +962 -75
- package/UI/Components/CommandPalette/PaletteRow.tsx +35 -3
- package/UI/Components/CommandPalette/Types.ts +37 -1
- package/UI/Components/CustomFields/CustomFieldsDetail.tsx +6 -0
- package/UI/Components/Detail/Detail.tsx +52 -15
- package/UI/Components/Detail/DetailRecordLine.tsx +96 -0
- package/UI/Components/Detail/DetailRecordTime.ts +196 -0
- package/UI/Components/Dropdown/DropdownChange.ts +198 -0
- package/UI/Components/EntityDropdown/EntityDropdown.tsx +270 -106
- package/UI/Components/EntityDropdown/EntityDropdownQuery.ts +119 -0
- package/UI/Components/FilePicker/FilePicker.tsx +90 -6
- package/UI/Components/FoldedSection/FoldedSection.tsx +370 -0
- package/UI/Components/FoldedSection/FoldedSectionItem.ts +141 -0
- package/UI/Components/FoldedSection/FoldedSectionTitles.ts +39 -0
- package/UI/Components/FormModal/BasicFormModal.tsx +40 -67
- package/UI/Components/Forms/BasicForm.tsx +218 -119
- package/UI/Components/Forms/BasicModelForm.tsx +0 -2
- package/UI/Components/Forms/CollapsibleFormSection.tsx +108 -18
- package/UI/Components/Forms/Fields/FormField.tsx +62 -15
- package/UI/Components/Forms/Fields/GeneratedKeyField.tsx +1 -5
- package/UI/Components/Forms/FormSummary.tsx +5 -3
- package/UI/Components/Forms/ModelForm.tsx +123 -16
- package/UI/Components/Forms/Types/Field.ts +98 -16
- package/UI/Components/Forms/Utils/AdvancedFormSection.ts +102 -31
- package/UI/Components/Forms/Utils/CreateFormDefaults.ts +158 -17
- package/UI/Components/Forms/Utils/FoldedFormFields.ts +393 -0
- package/UI/Components/Forms/Utils/FollowPickName.ts +52 -0
- package/UI/Components/Forms/Utils/FormModalWidth.ts +35 -4
- package/UI/Components/Forms/Utils/OpenFormSections.ts +104 -0
- package/UI/Components/Forms/Utils/SteppedFormFooter.ts +151 -0
- package/UI/Components/Forms/Utils/UniqueName.ts +81 -0
- package/UI/Components/LabelRule/ImportLabelRulesModal.tsx +22 -3
- package/UI/Components/MemberRoleAssignment/MemberRoleAssignment.tsx +6 -5
- package/UI/Components/Modal/ModalFooter.tsx +10 -1
- package/UI/Components/ModelDetail/CardModelDetail.tsx +33 -8
- package/UI/Components/ModelFormModal/ModelFormModal.tsx +44 -58
- package/UI/Components/ModelSwitch/ModelSwitchCard.tsx +305 -0
- package/UI/Components/ModelSwitch/ModelSwitchEvents.ts +109 -0
- package/UI/Components/ModelSwitch/ModelSwitchRow.tsx +438 -0
- package/UI/Components/ModelSwitch/ModelSwitchUtil.ts +120 -0
- package/UI/Components/ModelSwitch/ModelSwitchesCard.tsx +265 -0
- package/UI/Components/ModelSwitch/useSaveModelSwitch.ts +144 -0
- package/UI/Components/ModelTable/BaseModelTable.tsx +6 -0
- package/UI/Components/ModelTable/ModelTable.tsx +5 -0
- package/UI/Components/Navbar/NavBar.tsx +10 -9
- package/UI/Components/Navbar/NavBarMenuCatalog.ts +57 -22
- package/UI/Components/Navbar/NavBarMenuModal.tsx +17 -13
- package/UI/Components/Navbar/NavBarMobileMenu.tsx +40 -23
- package/UI/Components/Page/ModelHeaderEvents.ts +75 -0
- package/UI/Components/Page/ModelPage.tsx +21 -1
- package/UI/Components/Page/Page.tsx +68 -13
- package/UI/Components/PeoplePicker/PeoplePicker.tsx +150 -45
- package/UI/Components/PeoplePicker/PeoplePickerTypes.ts +193 -4
- package/UI/Components/PeoplePicker/PeopleSearchPopup.tsx +37 -10
- package/UI/Components/PublicForm/PublicFormFavicon.ts +99 -0
- package/UI/Components/PublicForm/PublicFormLogo.tsx +81 -0
- package/UI/Components/RuleCriteria/RuleCriteriaBuilder.tsx +5 -3
- package/UI/Components/RuleRun/RuleView.tsx +2 -5
- package/UI/Components/SaveStatus/SaveStatus.tsx +76 -0
- package/UI/Components/SaveStatus/useSaveOnChange.ts +178 -0
- package/UI/Components/SmtpConfig/SmtpConfigFormFields.ts +815 -0
- package/UI/Components/Sso/OidcProviderFormFields.ts +481 -0
- package/UI/Components/Sso/SamlProviderFormFields.ts +322 -0
- package/UI/Components/Sso/SsoProviderFormFields.ts +331 -0
- package/UI/Components/Table/TableEmptyState.tsx +39 -5
- package/UI/Components/Workflow/ArgumentsForm.tsx +21 -78
- package/UI/Components/Workflow/ComponentPicker/ComponentSearch.ts +18 -145
- package/UI/Components/Workflow/WorkflowLogModal.tsx +1 -3
- package/UI/Types/UseAnchoredFieldPopup.ts +46 -4
- package/UI/Utils/DefaultInviteTeam.ts +306 -0
- package/UI/Utils/GrantablePermission.ts +46 -0
- package/UI/Utils/PermissionGate.ts +80 -7
- package/UI/Utils/TranslateTemplate.ts +22 -0
- package/Utils/DistinctColor.ts +223 -0
- package/Utils/Monitor/MonitorOverviewPresentationUtil.ts +47 -2
- package/Utils/Slo/SloHealth.ts +9 -3
- package/Utils/StatusPage/ReportSchedule.ts +462 -0
- package/Utils/Telemetry/DiscoveredResourceName.ts +95 -0
- package/Utils/WordMatch.ts +185 -0
- package/build/dist/Models/DatabaseModels/AlertGroupingRule.js +6 -6
- package/build/dist/Models/DatabaseModels/AlertGroupingRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/File.js +47 -1
- package/build/dist/Models/DatabaseModels/File.js.map +1 -1
- package/build/dist/Models/DatabaseModels/Form.js +125 -0
- package/build/dist/Models/DatabaseModels/Form.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentGroupingRule.js +6 -6
- package/build/dist/Models/DatabaseModels/IncidentGroupingRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/LogDropFilter.js +1 -0
- package/build/dist/Models/DatabaseModels/LogDropFilter.js.map +1 -1
- package/build/dist/Models/DatabaseModels/LogPipeline.js +1 -0
- package/build/dist/Models/DatabaseModels/LogPipeline.js.map +1 -1
- package/build/dist/Models/DatabaseModels/LogScrubRule.js +14 -8
- package/build/dist/Models/DatabaseModels/LogScrubRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/MetricRecordingRule.js +1 -1
- package/build/dist/Models/DatabaseModels/MetricRecordingRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyExecutionLogTimeline.js +2 -2
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyExecutionLogTimeline.js.map +1 -1
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyUserOverride.js +20 -9
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyUserOverride.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ProjectCallSMSConfig.js +6 -1
- package/build/dist/Models/DatabaseModels/ProjectCallSMSConfig.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPage.js +4 -4
- package/build/dist/Models/DatabaseModels/StatusPage.js.map +1 -1
- package/build/dist/Models/DatabaseModels/TraceDropFilter.js +1 -0
- package/build/dist/Models/DatabaseModels/TraceDropFilter.js.map +1 -1
- package/build/dist/Models/DatabaseModels/TracePipeline.js +1 -0
- package/build/dist/Models/DatabaseModels/TracePipeline.js.map +1 -1
- package/build/dist/Models/DatabaseModels/TraceRecordingRule.js +1 -1
- package/build/dist/Models/DatabaseModels/TraceRecordingRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/TraceScrubRule.js +14 -8
- package/build/dist/Models/DatabaseModels/TraceScrubRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserOnCallLog.js +2 -2
- package/build/dist/Models/DatabaseModels/UserOnCallLog.js.map +1 -1
- package/build/dist/Server/API/CustomDomainRoutes.js +124 -0
- package/build/dist/Server/API/CustomDomainRoutes.js.map +1 -0
- package/build/dist/Server/API/DashboardAPI.js +22 -4
- package/build/dist/Server/API/DashboardAPI.js.map +1 -1
- package/build/dist/Server/API/DashboardDomainAPI.js +56 -49
- package/build/dist/Server/API/DashboardDomainAPI.js.map +1 -1
- package/build/dist/Server/API/StatusPageAPI.js +101 -39
- package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
- package/build/dist/Server/API/StatusPageDomainAPI.js +52 -51
- package/build/dist/Server/API/StatusPageDomainAPI.js.map +1 -1
- package/build/dist/Server/Infrastructure/GlobalCache.js +63 -0
- package/build/dist/Server/Infrastructure/GlobalCache.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1797700000000-AddFormBranding.js +36 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1797700000000-AddFormBranding.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +2 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Services/AlertGroupingEngineService.js +44 -61
- package/build/dist/Server/Services/AlertGroupingEngineService.js.map +1 -1
- package/build/dist/Server/Services/AlertGroupingRuleService.js +45 -0
- package/build/dist/Server/Services/AlertGroupingRuleService.js.map +1 -1
- package/build/dist/Server/Services/CephClusterService.js +23 -0
- package/build/dist/Server/Services/CephClusterService.js.map +1 -1
- package/build/dist/Server/Services/CloudResourceService.js +39 -0
- package/build/dist/Server/Services/CloudResourceService.js.map +1 -1
- package/build/dist/Server/Services/DashboardDomainService.js +510 -172
- package/build/dist/Server/Services/DashboardDomainService.js.map +1 -1
- package/build/dist/Server/Services/DashboardService.js +22 -9
- package/build/dist/Server/Services/DashboardService.js.map +1 -1
- package/build/dist/Server/Services/DatabaseService.js +114 -10
- package/build/dist/Server/Services/DatabaseService.js.map +1 -1
- package/build/dist/Server/Services/DockerHostService.js +51 -0
- package/build/dist/Server/Services/DockerHostService.js.map +1 -1
- package/build/dist/Server/Services/DockerSwarmClusterService.js +23 -0
- package/build/dist/Server/Services/DockerSwarmClusterService.js.map +1 -1
- package/build/dist/Server/Services/FileService.js +45 -0
- package/build/dist/Server/Services/FileService.js.map +1 -1
- package/build/dist/Server/Services/FormService.js +158 -14
- package/build/dist/Server/Services/FormService.js.map +1 -1
- package/build/dist/Server/Services/GlobalOidcService.js +9 -0
- package/build/dist/Server/Services/GlobalOidcService.js.map +1 -1
- package/build/dist/Server/Services/GlobalSsoService.js +9 -0
- package/build/dist/Server/Services/GlobalSsoService.js.map +1 -1
- package/build/dist/Server/Services/HostService.js +50 -0
- package/build/dist/Server/Services/HostService.js.map +1 -1
- package/build/dist/Server/Services/IncidentGroupingEngineService.js +45 -62
- package/build/dist/Server/Services/IncidentGroupingEngineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentGroupingRuleService.js +45 -0
- package/build/dist/Server/Services/IncidentGroupingRuleService.js.map +1 -1
- package/build/dist/Server/Services/IoTFleetService.js +23 -0
- package/build/dist/Server/Services/IoTFleetService.js.map +1 -1
- package/build/dist/Server/Services/KubernetesClusterService.js +54 -0
- package/build/dist/Server/Services/KubernetesClusterService.js.map +1 -1
- package/build/dist/Server/Services/LabelService.js +6 -16
- package/build/dist/Server/Services/LabelService.js.map +1 -1
- package/build/dist/Server/Services/LogScrubRuleService.js +31 -0
- package/build/dist/Server/Services/LogScrubRuleService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyScheduleService.js +202 -0
- package/build/dist/Server/Services/OnCallDutyPolicyScheduleService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyUserOverrideService.js +7 -1
- package/build/dist/Server/Services/OnCallDutyPolicyUserOverrideService.js.map +1 -1
- package/build/dist/Server/Services/OnCallNotificationAlertingService.js +17 -24
- package/build/dist/Server/Services/OnCallNotificationAlertingService.js.map +1 -1
- package/build/dist/Server/Services/OnCallSetupReminderService.js +32 -38
- package/build/dist/Server/Services/OnCallSetupReminderService.js.map +1 -1
- package/build/dist/Server/Services/PodmanHostService.js +51 -0
- package/build/dist/Server/Services/PodmanHostService.js.map +1 -1
- package/build/dist/Server/Services/ProfileAggregationService.js +34 -0
- package/build/dist/Server/Services/ProfileAggregationService.js.map +1 -1
- package/build/dist/Server/Services/ProjectCallSMSConfigService.js +53 -3
- package/build/dist/Server/Services/ProjectCallSMSConfigService.js.map +1 -1
- package/build/dist/Server/Services/ProjectOidcService.js +28 -0
- package/build/dist/Server/Services/ProjectOidcService.js.map +1 -1
- package/build/dist/Server/Services/ProjectSsoService.js +28 -0
- package/build/dist/Server/Services/ProjectSsoService.js.map +1 -1
- package/build/dist/Server/Services/ProxmoxClusterService.js +23 -0
- package/build/dist/Server/Services/ProxmoxClusterService.js.map +1 -1
- package/build/dist/Server/Services/RumApplicationService.js +42 -0
- package/build/dist/Server/Services/RumApplicationService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenanceService.js +18 -26
- package/build/dist/Server/Services/ScheduledMaintenanceService.js.map +1 -1
- package/build/dist/Server/Services/ServerlessFunctionService.js +44 -0
- package/build/dist/Server/Services/ServerlessFunctionService.js.map +1 -1
- package/build/dist/Server/Services/ServiceService.js +30 -4
- package/build/dist/Server/Services/ServiceService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageDomainService.js +495 -174
- package/build/dist/Server/Services/StatusPageDomainService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageOidcService.js +28 -0
- package/build/dist/Server/Services/StatusPageOidcService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageResourceService.js +82 -46
- package/build/dist/Server/Services/StatusPageResourceService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageService.js +174 -45
- package/build/dist/Server/Services/StatusPageService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageSsoService.js +28 -0
- package/build/dist/Server/Services/StatusPageSsoService.js.map +1 -1
- package/build/dist/Server/Services/TraceScrubRuleService.js +31 -0
- package/build/dist/Server/Services/TraceScrubRuleService.js.map +1 -1
- package/build/dist/Server/Services/UserIncomingCallNumberService.js +20 -10
- package/build/dist/Server/Services/UserIncomingCallNumberService.js.map +1 -1
- package/build/dist/Server/Services/VMwareVCenterService.js +23 -0
- package/build/dist/Server/Services/VMwareVCenterService.js.map +1 -1
- package/build/dist/Server/Utils/AI/PerfEvidence/SpanTreeAnalyzer.js +3 -3
- package/build/dist/Server/Utils/AI/PerfEvidence/SpanTreeAnalyzer.js.map +1 -1
- package/build/dist/Server/Utils/Greenlock/CertificateOrder.js +353 -0
- package/build/dist/Server/Utils/Greenlock/CertificateOrder.js.map +1 -0
- package/build/dist/Server/Utils/Greenlock/CertificateOrderBudget.js +119 -0
- package/build/dist/Server/Utils/Greenlock/CertificateOrderBudget.js.map +1 -0
- package/build/dist/Server/Utils/Greenlock/CertificateOrderFailures.js +208 -0
- package/build/dist/Server/Utils/Greenlock/CertificateOrderFailures.js.map +1 -0
- package/build/dist/Server/Utils/Greenlock/CertificateOrderLock.js +111 -0
- package/build/dist/Server/Utils/Greenlock/CertificateOrderLock.js.map +1 -0
- package/build/dist/Server/Utils/Greenlock/CertificateOrderOutcome.js +30 -0
- package/build/dist/Server/Utils/Greenlock/CertificateOrderOutcome.js.map +1 -0
- package/build/dist/Server/Utils/Greenlock/CertificateOwners.js +52 -0
- package/build/dist/Server/Utils/Greenlock/CertificateOwners.js.map +1 -0
- package/build/dist/Server/Utils/Greenlock/CertificateReissueOrder.js +80 -0
- package/build/dist/Server/Utils/Greenlock/CertificateReissueOrder.js.map +1 -0
- package/build/dist/Server/Utils/Greenlock/CustomDomainOrders.js +296 -0
- package/build/dist/Server/Utils/Greenlock/CustomDomainOrders.js.map +1 -0
- package/build/dist/Server/Utils/Greenlock/Greenlock.js +595 -146
- package/build/dist/Server/Utils/Greenlock/Greenlock.js.map +1 -1
- package/build/dist/Server/Utils/Rules/GroupingRuleEpisodeOwners.js +366 -0
- package/build/dist/Server/Utils/Rules/GroupingRuleEpisodeOwners.js.map +1 -0
- package/build/dist/Server/Utils/Rules/OwnerRuleAssignment.js +7 -0
- package/build/dist/Server/Utils/Rules/OwnerRuleAssignment.js.map +1 -1
- package/build/dist/Server/Utils/ScrubRuleValidation.js +127 -0
- package/build/dist/Server/Utils/ScrubRuleValidation.js.map +1 -0
- package/build/dist/Server/Utils/StatusPage/AffectedStatusPageResources.js +97 -0
- package/build/dist/Server/Utils/StatusPage/AffectedStatusPageResources.js.map +1 -0
- package/build/dist/Server/Utils/StatusPage/StatusPagesListingMonitorsBuilder.js +195 -0
- package/build/dist/Server/Utils/StatusPage/StatusPagesListingMonitorsBuilder.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/DiscoveredResourceCreate.js +177 -0
- package/build/dist/Server/Utils/Telemetry/DiscoveredResourceCreate.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/DiscoveredResourceUpdate.js +129 -0
- package/build/dist/Server/Utils/Telemetry/DiscoveredResourceUpdate.js.map +1 -0
- package/build/dist/Server/Utils/Telemetry/MessageQueueDiscovery.js +8 -2
- package/build/dist/Server/Utils/Telemetry/MessageQueueDiscovery.js.map +1 -1
- package/build/dist/Types/BrandColors.js +9 -0
- package/build/dist/Types/BrandColors.js.map +1 -1
- package/build/dist/Types/CustomDomain/CustomDomainCertificates.js +71 -0
- package/build/dist/Types/CustomDomain/CustomDomainCertificates.js.map +1 -0
- package/build/dist/Types/CustomDomain/CustomDomainVerification.js +58 -0
- package/build/dist/Types/CustomDomain/CustomDomainVerification.js.map +1 -0
- package/build/dist/Types/Dashboard/DashboardAccess.js +157 -0
- package/build/dist/Types/Dashboard/DashboardAccess.js.map +1 -0
- package/build/dist/Types/Dashboard/DashboardTemplates.js +26 -0
- package/build/dist/Types/Dashboard/DashboardTemplates.js.map +1 -1
- package/build/dist/Types/Filter/FilterConditionUtil.js +24 -0
- package/build/dist/Types/Filter/FilterConditionUtil.js.map +1 -0
- package/build/dist/Types/Form/FormBranding.js +266 -0
- package/build/dist/Types/Form/FormBranding.js.map +1 -0
- package/build/dist/Types/Form/FormPublic.js +6 -0
- package/build/dist/Types/Form/FormPublic.js.map +1 -1
- package/build/dist/Types/IncomingCall/IncomingCallRingTime.js +37 -0
- package/build/dist/Types/IncomingCall/IncomingCallRingTime.js.map +1 -0
- package/build/dist/Types/Log/LogScrubField.js +15 -0
- package/build/dist/Types/Log/LogScrubField.js.map +1 -0
- package/build/dist/Types/Monitor/SeriesContext/SeriesLabelDisplay.js +1 -1
- package/build/dist/Types/Monitor/SeriesContext/SeriesLabelDisplay.js.map +1 -1
- package/build/dist/Types/NotificationRule/OnCallRuleKind.js +134 -0
- package/build/dist/Types/NotificationRule/OnCallRuleKind.js.map +1 -0
- package/build/dist/Types/OnCallDutyPolicy/FirstResponders.js +2 -23
- package/build/dist/Types/OnCallDutyPolicy/FirstResponders.js.map +1 -1
- package/build/dist/Types/OnCallDutyPolicy/MiscDataId.js +30 -0
- package/build/dist/Types/OnCallDutyPolicy/MiscDataId.js.map +1 -0
- package/build/dist/Types/OnCallDutyPolicy/ScheduleFirstLayer.js +113 -0
- package/build/dist/Types/OnCallDutyPolicy/ScheduleFirstLayer.js.map +1 -0
- package/build/dist/Types/OnCallDutyPolicy/ScheduleLayerDefaults.js +95 -0
- package/build/dist/Types/OnCallDutyPolicy/ScheduleLayerDefaults.js.map +1 -0
- package/build/dist/Types/OnCallDutyPolicy/UserOverrideCoverRequest.js +99 -0
- package/build/dist/Types/OnCallDutyPolicy/UserOverrideCoverRequest.js.map +1 -0
- package/build/dist/Types/SSO/OidcProviderDefaults.js +189 -0
- package/build/dist/Types/SSO/OidcProviderDefaults.js.map +1 -0
- package/build/dist/Types/SSO/SamlProviderDefaults.js +55 -0
- package/build/dist/Types/SSO/SamlProviderDefaults.js.map +1 -0
- package/build/dist/Types/SSO/SsoProviderDefaults.js +67 -0
- package/build/dist/Types/SSO/SsoProviderDefaults.js.map +1 -0
- package/build/dist/Types/StatusPage/StatusPageAccess.js +132 -0
- package/build/dist/Types/StatusPage/StatusPageAccess.js.map +1 -0
- package/build/dist/Types/StatusPage/StatusPagesListingMonitors.js +84 -0
- package/build/dist/Types/StatusPage/StatusPagesListingMonitors.js.map +1 -0
- package/build/dist/Types/Telemetry/ScrubRule.js +180 -0
- package/build/dist/Types/Telemetry/ScrubRule.js.map +1 -0
- package/build/dist/UI/Components/AdvancedPageSection/AdvancedPageSection.js +9 -7
- package/build/dist/UI/Components/AdvancedPageSection/AdvancedPageSection.js.map +1 -1
- package/build/dist/UI/Components/Card/Card.js +81 -35
- package/build/dist/UI/Components/Card/Card.js.map +1 -1
- package/build/dist/UI/Components/ChoiceRows/ChoiceRows.js +54 -0
- package/build/dist/UI/Components/ChoiceRows/ChoiceRows.js.map +1 -0
- package/build/dist/UI/Components/CommandPalette/CommandPalette.js +25 -12
- package/build/dist/UI/Components/CommandPalette/CommandPalette.js.map +1 -1
- package/build/dist/UI/Components/CommandPalette/PaletteFilter.js +632 -64
- package/build/dist/UI/Components/CommandPalette/PaletteFilter.js.map +1 -1
- package/build/dist/UI/Components/CommandPalette/PaletteRow.js +7 -1
- package/build/dist/UI/Components/CommandPalette/PaletteRow.js.map +1 -1
- package/build/dist/UI/Components/CustomFields/CustomFieldsDetail.js +7 -1
- package/build/dist/UI/Components/CustomFields/CustomFieldsDetail.js.map +1 -1
- package/build/dist/UI/Components/Detail/Detail.js +26 -13
- package/build/dist/UI/Components/Detail/Detail.js.map +1 -1
- package/build/dist/UI/Components/Detail/DetailRecordLine.js +32 -0
- package/build/dist/UI/Components/Detail/DetailRecordLine.js.map +1 -0
- package/build/dist/UI/Components/Detail/DetailRecordTime.js +134 -0
- package/build/dist/UI/Components/Detail/DetailRecordTime.js.map +1 -0
- package/build/dist/UI/Components/Dropdown/DropdownChange.js +102 -0
- package/build/dist/UI/Components/Dropdown/DropdownChange.js.map +1 -0
- package/build/dist/UI/Components/EntityDropdown/EntityDropdown.js +134 -57
- package/build/dist/UI/Components/EntityDropdown/EntityDropdown.js.map +1 -1
- package/build/dist/UI/Components/EntityDropdown/EntityDropdownQuery.js +78 -0
- package/build/dist/UI/Components/EntityDropdown/EntityDropdownQuery.js.map +1 -0
- package/build/dist/UI/Components/FilePicker/FilePicker.js +55 -6
- package/build/dist/UI/Components/FilePicker/FilePicker.js.map +1 -1
- package/build/dist/UI/Components/FoldedSection/FoldedSection.js +139 -0
- package/build/dist/UI/Components/FoldedSection/FoldedSection.js.map +1 -0
- package/build/dist/UI/Components/FoldedSection/FoldedSectionItem.js +58 -0
- package/build/dist/UI/Components/FoldedSection/FoldedSectionItem.js.map +1 -0
- package/build/dist/UI/Components/FoldedSection/FoldedSectionTitles.js +34 -0
- package/build/dist/UI/Components/FoldedSection/FoldedSectionTitles.js.map +1 -0
- package/build/dist/UI/Components/FormModal/BasicFormModal.js +29 -45
- package/build/dist/UI/Components/FormModal/BasicFormModal.js.map +1 -1
- package/build/dist/UI/Components/Forms/BasicForm.js +148 -89
- package/build/dist/UI/Components/Forms/BasicForm.js.map +1 -1
- package/build/dist/UI/Components/Forms/BasicModelForm.js +1 -1
- package/build/dist/UI/Components/Forms/BasicModelForm.js.map +1 -1
- package/build/dist/UI/Components/Forms/CollapsibleFormSection.js +49 -10
- package/build/dist/UI/Components/Forms/CollapsibleFormSection.js.map +1 -1
- package/build/dist/UI/Components/Forms/Fields/FormField.js +25 -11
- package/build/dist/UI/Components/Forms/Fields/FormField.js.map +1 -1
- package/build/dist/UI/Components/Forms/Fields/GeneratedKeyField.js +2 -5
- package/build/dist/UI/Components/Forms/Fields/GeneratedKeyField.js.map +1 -1
- package/build/dist/UI/Components/Forms/FormSummary.js +5 -3
- package/build/dist/UI/Components/Forms/FormSummary.js.map +1 -1
- package/build/dist/UI/Components/Forms/ModelForm.js +72 -14
- package/build/dist/UI/Components/Forms/ModelForm.js.map +1 -1
- package/build/dist/UI/Components/Forms/Types/Field.js.map +1 -1
- package/build/dist/UI/Components/Forms/Utils/AdvancedFormSection.js +80 -23
- package/build/dist/UI/Components/Forms/Utils/AdvancedFormSection.js.map +1 -1
- package/build/dist/UI/Components/Forms/Utils/CreateFormDefaults.js +91 -9
- package/build/dist/UI/Components/Forms/Utils/CreateFormDefaults.js.map +1 -1
- package/build/dist/UI/Components/Forms/Utils/FoldedFormFields.js +243 -0
- package/build/dist/UI/Components/Forms/Utils/FoldedFormFields.js.map +1 -0
- package/build/dist/UI/Components/Forms/Utils/FollowPickName.js +32 -0
- package/build/dist/UI/Components/Forms/Utils/FollowPickName.js.map +1 -0
- package/build/dist/UI/Components/Forms/Utils/FormModalWidth.js +25 -5
- package/build/dist/UI/Components/Forms/Utils/FormModalWidth.js.map +1 -1
- package/build/dist/UI/Components/Forms/Utils/OpenFormSections.js +32 -0
- package/build/dist/UI/Components/Forms/Utils/OpenFormSections.js.map +1 -0
- package/build/dist/UI/Components/Forms/Utils/SteppedFormFooter.js +71 -0
- package/build/dist/UI/Components/Forms/Utils/SteppedFormFooter.js.map +1 -0
- package/build/dist/UI/Components/Forms/Utils/UniqueName.js +56 -0
- package/build/dist/UI/Components/Forms/Utils/UniqueName.js.map +1 -0
- package/build/dist/UI/Components/LabelRule/ImportLabelRulesModal.js +17 -1
- package/build/dist/UI/Components/LabelRule/ImportLabelRulesModal.js.map +1 -1
- package/build/dist/UI/Components/MemberRoleAssignment/MemberRoleAssignment.js +1 -2
- package/build/dist/UI/Components/MemberRoleAssignment/MemberRoleAssignment.js.map +1 -1
- package/build/dist/UI/Components/Modal/ModalFooter.js +8 -1
- package/build/dist/UI/Components/Modal/ModalFooter.js.map +1 -1
- package/build/dist/UI/Components/ModelDetail/CardModelDetail.js +19 -6
- package/build/dist/UI/Components/ModelDetail/CardModelDetail.js.map +1 -1
- package/build/dist/UI/Components/ModelFormModal/ModelFormModal.js +33 -43
- package/build/dist/UI/Components/ModelFormModal/ModelFormModal.js.map +1 -1
- package/build/dist/UI/Components/ModelSwitch/ModelSwitchCard.js +151 -0
- package/build/dist/UI/Components/ModelSwitch/ModelSwitchCard.js.map +1 -0
- package/build/dist/UI/Components/ModelSwitch/ModelSwitchEvents.js +54 -0
- package/build/dist/UI/Components/ModelSwitch/ModelSwitchEvents.js.map +1 -0
- package/build/dist/UI/Components/ModelSwitch/ModelSwitchRow.js +201 -0
- package/build/dist/UI/Components/ModelSwitch/ModelSwitchRow.js.map +1 -0
- package/build/dist/UI/Components/ModelSwitch/ModelSwitchUtil.js +60 -0
- package/build/dist/UI/Components/ModelSwitch/ModelSwitchUtil.js.map +1 -0
- package/build/dist/UI/Components/ModelSwitch/ModelSwitchesCard.js +116 -0
- package/build/dist/UI/Components/ModelSwitch/ModelSwitchesCard.js.map +1 -0
- package/build/dist/UI/Components/ModelSwitch/useSaveModelSwitch.js +68 -0
- package/build/dist/UI/Components/ModelSwitch/useSaveModelSwitch.js.map +1 -0
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js +1 -0
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/ModelTable.js +3 -1
- package/build/dist/UI/Components/ModelTable/ModelTable.js.map +1 -1
- package/build/dist/UI/Components/Navbar/NavBar.js +2 -2
- package/build/dist/UI/Components/Navbar/NavBar.js.map +1 -1
- package/build/dist/UI/Components/Navbar/NavBarMenuCatalog.js +21 -10
- package/build/dist/UI/Components/Navbar/NavBarMenuCatalog.js.map +1 -1
- package/build/dist/UI/Components/Navbar/NavBarMenuModal.js +10 -7
- package/build/dist/UI/Components/Navbar/NavBarMenuModal.js.map +1 -1
- package/build/dist/UI/Components/Navbar/NavBarMobileMenu.js +17 -9
- package/build/dist/UI/Components/Navbar/NavBarMobileMenu.js.map +1 -1
- package/build/dist/UI/Components/Page/ModelHeaderEvents.js +43 -0
- package/build/dist/UI/Components/Page/ModelHeaderEvents.js.map +1 -0
- package/build/dist/UI/Components/Page/ModelPage.js +19 -1
- package/build/dist/UI/Components/Page/ModelPage.js.map +1 -1
- package/build/dist/UI/Components/Page/Page.js +31 -13
- package/build/dist/UI/Components/Page/Page.js.map +1 -1
- package/build/dist/UI/Components/PeoplePicker/PeoplePicker.js +62 -20
- package/build/dist/UI/Components/PeoplePicker/PeoplePicker.js.map +1 -1
- package/build/dist/UI/Components/PeoplePicker/PeoplePickerTypes.js +98 -1
- package/build/dist/UI/Components/PeoplePicker/PeoplePickerTypes.js.map +1 -1
- package/build/dist/UI/Components/PeoplePicker/PeopleSearchPopup.js +35 -14
- package/build/dist/UI/Components/PeoplePicker/PeopleSearchPopup.js.map +1 -1
- package/build/dist/UI/Components/PublicForm/PublicFormFavicon.js +66 -0
- package/build/dist/UI/Components/PublicForm/PublicFormFavicon.js.map +1 -0
- package/build/dist/UI/Components/PublicForm/PublicFormLogo.js +38 -0
- package/build/dist/UI/Components/PublicForm/PublicFormLogo.js.map +1 -0
- package/build/dist/UI/Components/RuleCriteria/RuleCriteriaBuilder.js +5 -3
- package/build/dist/UI/Components/RuleCriteria/RuleCriteriaBuilder.js.map +1 -1
- package/build/dist/UI/Components/RuleRun/RuleView.js +2 -2
- package/build/dist/UI/Components/RuleRun/RuleView.js.map +1 -1
- package/build/dist/UI/Components/SaveStatus/SaveStatus.js +46 -0
- package/build/dist/UI/Components/SaveStatus/SaveStatus.js.map +1 -0
- package/build/dist/UI/Components/SaveStatus/useSaveOnChange.js +98 -0
- package/build/dist/UI/Components/SaveStatus/useSaveOnChange.js.map +1 -0
- package/build/dist/UI/Components/SmtpConfig/SmtpConfigFormFields.js +503 -0
- package/build/dist/UI/Components/SmtpConfig/SmtpConfigFormFields.js.map +1 -0
- package/build/dist/UI/Components/Sso/OidcProviderFormFields.js +283 -0
- package/build/dist/UI/Components/Sso/OidcProviderFormFields.js.map +1 -0
- package/build/dist/UI/Components/Sso/SamlProviderFormFields.js +182 -0
- package/build/dist/UI/Components/Sso/SamlProviderFormFields.js.map +1 -0
- package/build/dist/UI/Components/Sso/SsoProviderFormFields.js +208 -0
- package/build/dist/UI/Components/Sso/SsoProviderFormFields.js.map +1 -0
- package/build/dist/UI/Components/Table/TableEmptyState.js +17 -4
- package/build/dist/UI/Components/Table/TableEmptyState.js.map +1 -1
- package/build/dist/UI/Components/Workflow/ArgumentsForm.js +17 -52
- package/build/dist/UI/Components/Workflow/ArgumentsForm.js.map +1 -1
- package/build/dist/UI/Components/Workflow/ComponentPicker/ComponentSearch.js +7 -89
- package/build/dist/UI/Components/Workflow/ComponentPicker/ComponentSearch.js.map +1 -1
- package/build/dist/UI/Components/Workflow/WorkflowLogModal.js +1 -1
- package/build/dist/UI/Components/Workflow/WorkflowLogModal.js.map +1 -1
- package/build/dist/UI/Types/UseAnchoredFieldPopup.js +22 -3
- package/build/dist/UI/Types/UseAnchoredFieldPopup.js.map +1 -1
- package/build/dist/UI/Utils/DefaultInviteTeam.js +207 -0
- package/build/dist/UI/Utils/DefaultInviteTeam.js.map +1 -0
- package/build/dist/UI/Utils/GrantablePermission.js +31 -0
- package/build/dist/UI/Utils/GrantablePermission.js.map +1 -1
- package/build/dist/UI/Utils/PermissionGate.js +54 -3
- package/build/dist/UI/Utils/PermissionGate.js.map +1 -1
- package/build/dist/UI/Utils/TranslateTemplate.js +16 -0
- package/build/dist/UI/Utils/TranslateTemplate.js.map +1 -1
- package/build/dist/Utils/DistinctColor.js +151 -0
- package/build/dist/Utils/DistinctColor.js.map +1 -0
- package/build/dist/Utils/Monitor/MonitorOverviewPresentationUtil.js +12 -1
- package/build/dist/Utils/Monitor/MonitorOverviewPresentationUtil.js.map +1 -1
- package/build/dist/Utils/Slo/SloHealth.js +9 -3
- package/build/dist/Utils/Slo/SloHealth.js.map +1 -1
- package/build/dist/Utils/StatusPage/ReportSchedule.js +304 -0
- package/build/dist/Utils/StatusPage/ReportSchedule.js.map +1 -0
- package/build/dist/Utils/Telemetry/DiscoveredResourceName.js +65 -0
- package/build/dist/Utils/Telemetry/DiscoveredResourceName.js.map +1 -0
- package/build/dist/Utils/WordMatch.js +115 -0
- package/build/dist/Utils/WordMatch.js.map +1 -0
- package/package.json +1 -1
- package/Tests/App/Dashboard/BulkChangeStateModalSteps.test.ts +0 -109
- package/Tests/App/StatusPage/StatusPageSubscribeFromFirstStep.test.tsx +0 -382
- package/Tests/UI/Components/Forms/BasicFormFinishFromAnyStep.test.tsx +0 -729
- package/Tests/UI/Components/Forms/FinishFromAnyStep.test.ts +0 -571
- package/Tests/UI/Components/Forms/FinishFromAnyStepGuard.test.ts +0 -566
- package/UI/Components/Forms/Utils/FinishFromAnyStep.ts +0 -284
- package/build/dist/UI/Components/Forms/Utils/FinishFromAnyStep.js +0 -132
- package/build/dist/UI/Components/Forms/Utils/FinishFromAnyStep.js.map +0 -1
|
@@ -13,7 +13,6 @@ import AcmeChallengeService from "../../Services/AcmeChallengeService";
|
|
|
13
13
|
import QueryHelper from "../../Types/Database/QueryHelper";
|
|
14
14
|
import logger from "../Logger";
|
|
15
15
|
import SortOrder from "../../../Types/BaseDatabase/SortOrder";
|
|
16
|
-
import LIMIT_MAX from "../../../Types/Database/LimitMax";
|
|
17
16
|
import OneUptimeDate from "../../../Types/Date";
|
|
18
17
|
import BadDataException from "../../../Types/Exception/BadDataException";
|
|
19
18
|
import Exception from "../../../Types/Exception/Exception";
|
|
@@ -21,9 +20,14 @@ import ServerException from "../../../Types/Exception/ServerException";
|
|
|
21
20
|
import Text from "../../../Types/Text";
|
|
22
21
|
import AcmeCertificate from "../../../Models/DatabaseModels/AcmeCertificate";
|
|
23
22
|
import AcmeChallenge from "../../../Models/DatabaseModels/AcmeChallenge";
|
|
23
|
+
import LIMIT_MAX from "../../../Types/Database/LimitMax";
|
|
24
24
|
import ArrayUtil from "../../../Utils/Array";
|
|
25
25
|
import acme from "acme-client";
|
|
26
26
|
import CaptureSpan from "../Telemetry/CaptureSpan";
|
|
27
|
+
import CertificateOrderLock from "./CertificateOrderLock";
|
|
28
|
+
import CertificateOrderBudget, { CertificateOrderReason, } from "./CertificateOrderBudget";
|
|
29
|
+
import CertificateOrderFailures from "./CertificateOrderFailures";
|
|
30
|
+
import { CertificateOrderOutcome } from "./CertificateOrderOutcome";
|
|
27
31
|
class GreenlockUtil {
|
|
28
32
|
/*
|
|
29
33
|
* Stable per-domain lead time, somewhere in the range above. Same domain,
|
|
@@ -38,18 +42,156 @@ class GreenlockUtil {
|
|
|
38
42
|
}
|
|
39
43
|
return (GreenlockUtil.RENEW_LEAD_TIME_MIN_IN_DAYS + (hash % (spanInDays + 1)));
|
|
40
44
|
}
|
|
45
|
+
/*
|
|
46
|
+
* Whether this certificate has reached its own renewal lead time. Expired
|
|
47
|
+
* certificates are due too.
|
|
48
|
+
*/
|
|
49
|
+
static isDueForRenewal(certificate, now) {
|
|
50
|
+
if (!certificate.domain || !certificate.expiresAt) {
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
const renewAt = OneUptimeDate.addRemoveDays(certificate.expiresAt, -GreenlockUtil.getRenewalLeadTimeInDays(certificate.domain));
|
|
54
|
+
return !OneUptimeDate.isAfter(renewAt, now);
|
|
55
|
+
}
|
|
56
|
+
/*
|
|
57
|
+
* The items a capped sweep works on in this run: at most max of them,
|
|
58
|
+
* chosen by a shuffle that is the same for every replica within one
|
|
59
|
+
* 15-minute window and different in the next, so an item whose work keeps
|
|
60
|
+
* failing cannot hold a slot run after run while the others wait. Every
|
|
61
|
+
* item has the same chance in every run, however the list grows, shrinks
|
|
62
|
+
* or is ordered, and whatever schedule the sweep runs on - a fixed
|
|
63
|
+
* rotation would skip items whenever earlier ones left the list.
|
|
64
|
+
*/
|
|
65
|
+
static pickForThisRun(data) {
|
|
66
|
+
const max = Math.max(Math.floor(data.max), 0);
|
|
67
|
+
const window = Math.floor(data.now.getTime() / OneUptimeDate.convertMinutesToMilliseconds(15));
|
|
68
|
+
return data.items
|
|
69
|
+
.map((item) => {
|
|
70
|
+
const key = data.getKey(item);
|
|
71
|
+
return {
|
|
72
|
+
item: item,
|
|
73
|
+
key: key,
|
|
74
|
+
rank: data.items.length <= max
|
|
75
|
+
? 0
|
|
76
|
+
: GreenlockUtil.hashText(`${window}:${key}`),
|
|
77
|
+
};
|
|
78
|
+
})
|
|
79
|
+
.sort((a, b) => {
|
|
80
|
+
if (a.rank !== b.rank) {
|
|
81
|
+
return a.rank - b.rank;
|
|
82
|
+
}
|
|
83
|
+
if (a.key === b.key) {
|
|
84
|
+
return 0;
|
|
85
|
+
}
|
|
86
|
+
return a.key < b.key ? -1 : 1;
|
|
87
|
+
})
|
|
88
|
+
.slice(0, max)
|
|
89
|
+
.map((ranked) => {
|
|
90
|
+
return ranked.item;
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
// 32-bit FNV-1a: a stable, well-spread hash of a string.
|
|
94
|
+
static hashText(text) {
|
|
95
|
+
let hash = 0x811c9dc5;
|
|
96
|
+
for (let i = 0; i < text.length; i++) {
|
|
97
|
+
hash ^= text.charCodeAt(i);
|
|
98
|
+
hash = Math.imul(hash, 0x01000193) >>> 0;
|
|
99
|
+
}
|
|
100
|
+
return hash;
|
|
101
|
+
}
|
|
102
|
+
/*
|
|
103
|
+
* The certificate each of these domains has in AcmeCertificate, if any,
|
|
104
|
+
* looked up DOMAIN_LOOKUP_CHUNK_SIZE names at a time. Where a name has more
|
|
105
|
+
* than one row, the one that expires last. A row without an expiry is no
|
|
106
|
+
* certificate at all: it is never due, so nothing would ever replace it if
|
|
107
|
+
* it counted as one.
|
|
108
|
+
*
|
|
109
|
+
* The sweeps that order first certificates and re-order missing ones read
|
|
110
|
+
* this to tell a domain that needs an order from one that only needs to be
|
|
111
|
+
* recorded as ordered.
|
|
112
|
+
*/
|
|
113
|
+
static async findCertificatesByDomain(domains) {
|
|
114
|
+
const certificates = new Map();
|
|
115
|
+
const uniqueDomains = Array.from(new Set(domains.filter((domain) => {
|
|
116
|
+
return domain.length > 0;
|
|
117
|
+
})));
|
|
118
|
+
for (let offset = 0; offset < uniqueDomains.length; offset += GreenlockUtil.DOMAIN_LOOKUP_CHUNK_SIZE) {
|
|
119
|
+
const chunk = uniqueDomains.slice(offset, offset + GreenlockUtil.DOMAIN_LOOKUP_CHUNK_SIZE);
|
|
120
|
+
const rows = await AcmeCertificateService.findBy({
|
|
121
|
+
query: {
|
|
122
|
+
domain: QueryHelper.any(chunk),
|
|
123
|
+
},
|
|
124
|
+
select: {
|
|
125
|
+
domain: true,
|
|
126
|
+
expiresAt: true,
|
|
127
|
+
},
|
|
128
|
+
limit: LIMIT_MAX,
|
|
129
|
+
skip: 0,
|
|
130
|
+
props: {
|
|
131
|
+
isRoot: true,
|
|
132
|
+
},
|
|
133
|
+
});
|
|
134
|
+
for (const row of rows) {
|
|
135
|
+
if (!row.domain || !row.expiresAt) {
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
const existing = certificates.get(row.domain);
|
|
139
|
+
if (!existing ||
|
|
140
|
+
OneUptimeDate.isAfter(row.expiresAt, existing.expiresAt)) {
|
|
141
|
+
certificates.set(row.domain, row);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
return certificates;
|
|
146
|
+
}
|
|
147
|
+
/*
|
|
148
|
+
* Ask one owner which of these domains are its own, a chunk at a time.
|
|
149
|
+
*/
|
|
150
|
+
static async getOwnedAmong(data) {
|
|
151
|
+
const owned = new Set();
|
|
152
|
+
const domains = Array.from(new Set(data.domains));
|
|
153
|
+
for (let offset = 0; offset < domains.length; offset += GreenlockUtil.DOMAIN_LOOKUP_CHUNK_SIZE) {
|
|
154
|
+
const chunk = domains.slice(offset, offset + GreenlockUtil.DOMAIN_LOOKUP_CHUNK_SIZE);
|
|
155
|
+
for (const domain of await data.getOwnedDomains(chunk)) {
|
|
156
|
+
owned.add(domain);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return owned;
|
|
160
|
+
}
|
|
161
|
+
/*
|
|
162
|
+
* Renew the caller's certificates that are due, at most maxPerRun of them
|
|
163
|
+
* per run (RENEW_MAX_PER_RUN unless the caller asks for fewer).
|
|
164
|
+
*
|
|
165
|
+
* AcmeCertificate is one table shared by every owner of a certificate:
|
|
166
|
+
* status page domains, dashboard domains and the installation's own
|
|
167
|
+
* primary host (CoreSSL). Each owner runs this on its own schedule and can
|
|
168
|
+
* only judge its own domains - its validateCname reports false for every
|
|
169
|
+
* domain it has no row for. So a run must never act on a certificate it
|
|
170
|
+
* does not own. Before getOwnedDomains existed, the status page run
|
|
171
|
+
* treated every dashboard certificate (and the primary host's, whenever
|
|
172
|
+
* its lead time came before CoreSSL's 30-day renewal) as a status page
|
|
173
|
+
* whose CNAME had stopped validating, and deleted it.
|
|
174
|
+
*
|
|
175
|
+
* getOwnedDomains is handed the due domains (a chunk at a time) and
|
|
176
|
+
* returns the ones the caller owns. Every due certificate is read, not a
|
|
177
|
+
* first page of them, and ownership is settled before the cap, so neither
|
|
178
|
+
* another owner's backlog nor a pile of expired certificates nobody owns
|
|
179
|
+
* can take this caller's slots. A certificate nobody claims is left exactly
|
|
180
|
+
* as it is: neither renewed nor removed
|
|
181
|
+
* (removeExpiredCertificatesNobodyOwns cleans those up once they are dead).
|
|
182
|
+
*/
|
|
41
183
|
static async renewAllCertsWhichAreExpiringSoon(data) {
|
|
184
|
+
var _a;
|
|
42
185
|
try {
|
|
43
186
|
logger.debug("Renewing all certificates");
|
|
44
187
|
/*
|
|
45
188
|
* Read the widest window any domain's lead time can make it due in, then
|
|
46
189
|
* keep only the domains whose own lead time has actually been reached.
|
|
47
190
|
*/
|
|
48
|
-
const certificates = await AcmeCertificateService.
|
|
191
|
+
const certificates = await AcmeCertificateService.findAllBy({
|
|
49
192
|
query: {
|
|
50
193
|
expiresAt: QueryHelper.lessThanEqualTo(OneUptimeDate.addRemoveDays(OneUptimeDate.getCurrentDate(), GreenlockUtil.RENEW_LEAD_TIME_MAX_IN_DAYS)),
|
|
51
194
|
},
|
|
52
|
-
limit: LIMIT_MAX,
|
|
53
195
|
skip: 0,
|
|
54
196
|
select: {
|
|
55
197
|
domain: true,
|
|
@@ -63,21 +205,84 @@ class GreenlockUtil {
|
|
|
63
205
|
},
|
|
64
206
|
});
|
|
65
207
|
const now = OneUptimeDate.getCurrentDate();
|
|
208
|
+
/*
|
|
209
|
+
* One renewal per name: a name can have more than one row, and a row
|
|
210
|
+
* renewed between two page reads can come back on both.
|
|
211
|
+
*/
|
|
212
|
+
const dueDomains = new Set();
|
|
66
213
|
const dueCertificates = certificates.filter((certificate) => {
|
|
67
|
-
if (!certificate
|
|
214
|
+
if (!GreenlockUtil.isDueForRenewal(certificate, now) ||
|
|
215
|
+
dueDomains.has(certificate.domain)) {
|
|
68
216
|
return false;
|
|
69
217
|
}
|
|
70
|
-
|
|
71
|
-
return
|
|
218
|
+
dueDomains.add(certificate.domain);
|
|
219
|
+
return true;
|
|
220
|
+
});
|
|
221
|
+
/*
|
|
222
|
+
* A lookup that fails throws out of the run before anything is renewed
|
|
223
|
+
* or removed: not knowing who owns a certificate is never a reason to
|
|
224
|
+
* touch it.
|
|
225
|
+
*/
|
|
226
|
+
const ownedDomains = await GreenlockUtil.getOwnedAmong({
|
|
227
|
+
domains: dueCertificates.map((certificate) => {
|
|
228
|
+
return certificate.domain;
|
|
229
|
+
}),
|
|
230
|
+
getOwnedDomains: data.getOwnedDomains,
|
|
231
|
+
});
|
|
232
|
+
const ownedDueCertificates = dueCertificates.filter((certificate) => {
|
|
233
|
+
return ownedDomains.has(certificate.domain);
|
|
234
|
+
});
|
|
235
|
+
/*
|
|
236
|
+
* A name whose last renewals failed - a CAA record that leaves Let's
|
|
237
|
+
* Encrypt out, a name Let's Encrypt has paused - waits longer after
|
|
238
|
+
* each failure in a row (CertificateOrderFailures) instead of taking a
|
|
239
|
+
* slot in every run. Each failed order counts against the account all
|
|
240
|
+
* the same, and Let's Encrypt allows five failed validations per name
|
|
241
|
+
* per hour.
|
|
242
|
+
*/
|
|
243
|
+
const renewableDueCertificates = await CertificateOrderFailures.withoutThoseWaitingToRetry({
|
|
244
|
+
items: ownedDueCertificates,
|
|
245
|
+
getDomain: (certificate) => {
|
|
246
|
+
return certificate.domain;
|
|
247
|
+
},
|
|
248
|
+
now: now,
|
|
72
249
|
});
|
|
250
|
+
const maxPerRun = Math.max(Math.min((_a = data.maxPerRun) !== null && _a !== void 0 ? _a : GreenlockUtil.RENEW_MAX_PER_RUN, GreenlockUtil.RENEW_MAX_PER_RUN), 0);
|
|
73
251
|
/*
|
|
74
252
|
* Still sorted by expiry, so a run that cannot take the whole backlog
|
|
75
253
|
* spends itself on the domains closest to expiring and leaves the rest -
|
|
76
254
|
* which by construction still have weeks of lead time - to the next run.
|
|
255
|
+
*
|
|
256
|
+
* Certificates that have already expired come after every one that can
|
|
257
|
+
* still be saved, and take turns among themselves. Such a domain has
|
|
258
|
+
* been failing to renew since its lead time began - a CAA record that
|
|
259
|
+
* leaves Let's Encrypt out, a name Let's Encrypt has paused - and,
|
|
260
|
+
* sorting first by expiry, it would otherwise take a slot in every run
|
|
261
|
+
* and starve the renewals behind it. It is still tried whenever slots
|
|
262
|
+
* are left, which in a run without a backlog is every run.
|
|
77
263
|
*/
|
|
78
|
-
const
|
|
79
|
-
|
|
264
|
+
const stillValid = renewableDueCertificates.filter((certificate) => {
|
|
265
|
+
return OneUptimeDate.isAfter(certificate.expiresAt, now);
|
|
266
|
+
});
|
|
267
|
+
const alreadyExpired = renewableDueCertificates.filter((certificate) => {
|
|
268
|
+
return !OneUptimeDate.isAfter(certificate.expiresAt, now);
|
|
269
|
+
});
|
|
270
|
+
const firstInLine = stillValid.slice(0, maxPerRun);
|
|
271
|
+
const batch = [
|
|
272
|
+
...firstInLine,
|
|
273
|
+
...GreenlockUtil.pickForThisRun({
|
|
274
|
+
items: alreadyExpired,
|
|
275
|
+
max: maxPerRun - firstInLine.length,
|
|
276
|
+
now: now,
|
|
277
|
+
getKey: (certificate) => {
|
|
278
|
+
return certificate.domain;
|
|
279
|
+
},
|
|
280
|
+
}),
|
|
281
|
+
];
|
|
282
|
+
logger.debug(`Found ${dueCertificates.length} certificates due for renewal, ${ownedDueCertificates.length} of them owned by this caller, ${ownedDueCertificates.length - renewableDueCertificates.length} of those waiting after failed orders, renewing ${batch.length} in this run`, {
|
|
80
283
|
dueCount: dueCertificates.length,
|
|
284
|
+
ownedDueCount: ownedDueCertificates.length,
|
|
285
|
+
waitingAfterFailureCount: ownedDueCertificates.length - renewableDueCertificates.length,
|
|
81
286
|
batchCount: batch.length,
|
|
82
287
|
});
|
|
83
288
|
await ArrayUtil.forEachWithConcurrency(batch, GreenlockUtil.RENEW_CONCURRENCY, async (certificate) => {
|
|
@@ -94,40 +299,166 @@ class GreenlockUtil {
|
|
|
94
299
|
throw e;
|
|
95
300
|
}
|
|
96
301
|
}
|
|
302
|
+
/*
|
|
303
|
+
* Delete certificates that have been expired for more than
|
|
304
|
+
* REMOVE_UNOWNED_AFTER_EXPIRY_IN_DAYS and that no owner claims, at most
|
|
305
|
+
* REMOVE_UNOWNED_MAX_PER_RUN per run. Returns how many were deleted.
|
|
306
|
+
*
|
|
307
|
+
* owners must name every kind of certificate owner there is (see
|
|
308
|
+
* CertificateOwners). A certificate is deleted only when all of them have
|
|
309
|
+
* answered and none claims it; if any lookup fails, nothing is deleted.
|
|
310
|
+
*
|
|
311
|
+
* The delete names the row's id AND that it is still expired, and
|
|
312
|
+
* hardDeleteBy keeps those conditions in the DELETE statement itself:
|
|
313
|
+
* orderCert renews a name by updating its row in place, so a row renewed at
|
|
314
|
+
* any point before the delete no longer matches and is kept. A newer row for
|
|
315
|
+
* the same name never matches either.
|
|
316
|
+
*/
|
|
317
|
+
static async removeExpiredCertificatesNobodyOwns(data) {
|
|
318
|
+
var _a;
|
|
319
|
+
const expiredBefore = OneUptimeDate.addRemoveDays(OneUptimeDate.getCurrentDate(), -GreenlockUtil.REMOVE_UNOWNED_AFTER_EXPIRY_IN_DAYS);
|
|
320
|
+
const expiredCertificates = await AcmeCertificateService.findAllBy({
|
|
321
|
+
query: {
|
|
322
|
+
expiresAt: QueryHelper.lessThan(expiredBefore),
|
|
323
|
+
},
|
|
324
|
+
select: {
|
|
325
|
+
_id: true,
|
|
326
|
+
domain: true,
|
|
327
|
+
expiresAt: true,
|
|
328
|
+
},
|
|
329
|
+
sort: {
|
|
330
|
+
expiresAt: SortOrder.Ascending,
|
|
331
|
+
},
|
|
332
|
+
skip: 0,
|
|
333
|
+
props: {
|
|
334
|
+
isRoot: true,
|
|
335
|
+
},
|
|
336
|
+
});
|
|
337
|
+
const candidates = expiredCertificates.filter((certificate) => {
|
|
338
|
+
return Boolean(certificate.domain) && Boolean(certificate.id);
|
|
339
|
+
});
|
|
340
|
+
if (candidates.length === 0) {
|
|
341
|
+
return 0;
|
|
342
|
+
}
|
|
343
|
+
const domains = candidates.map((certificate) => {
|
|
344
|
+
return certificate.domain;
|
|
345
|
+
});
|
|
346
|
+
const ownedDomains = new Set();
|
|
347
|
+
for (const owner of data.owners) {
|
|
348
|
+
const ownedByThisOwner = await GreenlockUtil.getOwnedAmong({
|
|
349
|
+
domains: domains,
|
|
350
|
+
getOwnedDomains: owner.getOwnedDomains,
|
|
351
|
+
});
|
|
352
|
+
for (const domain of ownedByThisOwner) {
|
|
353
|
+
ownedDomains.add(domain);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
const abandoned = candidates
|
|
357
|
+
.filter((certificate) => {
|
|
358
|
+
return !ownedDomains.has(certificate.domain);
|
|
359
|
+
})
|
|
360
|
+
.slice(0, GreenlockUtil.REMOVE_UNOWNED_MAX_PER_RUN);
|
|
361
|
+
let removedCount = 0;
|
|
362
|
+
for (const certificate of abandoned) {
|
|
363
|
+
logger.debug(`Deleting the certificate of ${certificate.domain}: it expired on ${(_a = certificate.expiresAt) === null || _a === void 0 ? void 0 : _a.toISOString()} and no status page, dashboard or primary host claims it.`, { domain: certificate.domain });
|
|
364
|
+
const deletedCount = await AcmeCertificateService.hardDeleteBy({
|
|
365
|
+
query: {
|
|
366
|
+
_id: certificate.id.toString(),
|
|
367
|
+
domain: certificate.domain,
|
|
368
|
+
expiresAt: QueryHelper.lessThan(expiredBefore),
|
|
369
|
+
},
|
|
370
|
+
limit: 1,
|
|
371
|
+
skip: 0,
|
|
372
|
+
props: {
|
|
373
|
+
isRoot: true,
|
|
374
|
+
},
|
|
375
|
+
});
|
|
376
|
+
removedCount += deletedCount;
|
|
377
|
+
}
|
|
378
|
+
return removedCount;
|
|
379
|
+
}
|
|
97
380
|
/*
|
|
98
381
|
* Renew one domain. Never throws: one domain that cannot be renewed - a CNAME
|
|
99
382
|
* that no longer points here, a challenge the CA would not accept - must not
|
|
100
383
|
* take down the rest of the run with it.
|
|
384
|
+
*
|
|
385
|
+
* The renewal runs with the name's order lock held, so it never overlaps a
|
|
386
|
+
* reissue, a Check now or a re-order of the same name, and it looks the
|
|
387
|
+
* certificate up again under that lock: one of those may have replaced it
|
|
388
|
+
* since this run read the table, and renewing it again would spend an
|
|
389
|
+
* order on a duplicate.
|
|
390
|
+
*
|
|
391
|
+
* A CNAME check that fails never deletes a certificate that is still
|
|
392
|
+
* valid. It used to, and a moment's DNS trouble during a renewal took a
|
|
393
|
+
* domain off HTTPS with weeks left on its certificate. Now the renewal is
|
|
394
|
+
* skipped while the certificate keeps serving, and the failure is
|
|
395
|
+
* recorded (CertificateOrderFailures): the domain's Status column says so,
|
|
396
|
+
* and the name waits before the next attempt, longer after each failure
|
|
397
|
+
* in a row - without that, a domain whose record really is gone would take
|
|
398
|
+
* a slot of every run until its certificate expired, and keep the
|
|
399
|
+
* renewals behind it waiting. Only a certificate that has already expired
|
|
400
|
+
* - it serves nobody - is removed when the check fails, so the domain is
|
|
401
|
+
* ordered afresh once its record is back.
|
|
101
402
|
*/
|
|
102
403
|
static async renewCertForDomain(data) {
|
|
404
|
+
var _a;
|
|
103
405
|
const { domain } = data;
|
|
104
406
|
const certLogAttributes = {
|
|
105
407
|
domain: domain,
|
|
106
408
|
};
|
|
107
409
|
logger.debug(`Renewing certificate for domain: ${domain}`, certLogAttributes);
|
|
410
|
+
const lock = await CertificateOrderLock.tryLock(domain);
|
|
411
|
+
if (!lock) {
|
|
412
|
+
logger.debug(`Not renewing the certificate of ${domain} now: another order for it is running. A later run renews it if it is still due.`, certLogAttributes);
|
|
413
|
+
return;
|
|
414
|
+
}
|
|
108
415
|
try {
|
|
109
|
-
|
|
416
|
+
const now = OneUptimeDate.getCurrentDate();
|
|
417
|
+
const certificate = (await GreenlockUtil.findCertificatesByDomain([lock.domain])).get(lock.domain);
|
|
418
|
+
if (!certificate) {
|
|
419
|
+
logger.debug(`Not renewing the certificate of ${domain}: it is gone. The domain's owner re-orders a missing certificate.`, certLogAttributes);
|
|
420
|
+
return;
|
|
421
|
+
}
|
|
422
|
+
if (!GreenlockUtil.isDueForRenewal(certificate, now)) {
|
|
423
|
+
logger.debug(`Not renewing the certificate of ${domain}: another order has renewed it since this run started.`, certLogAttributes);
|
|
424
|
+
return;
|
|
425
|
+
}
|
|
110
426
|
const isValidCname = await data.validateCname(domain);
|
|
111
427
|
if (!isValidCname) {
|
|
112
|
-
|
|
113
|
-
|
|
428
|
+
const hasExpired = !OneUptimeDate.isAfter(certificate.expiresAt, now);
|
|
429
|
+
if (!hasExpired) {
|
|
430
|
+
logger.debug(`CNAME of ${domain} did not validate: keeping its certificate, valid until ${(_a = certificate.expiresAt) === null || _a === void 0 ? void 0 : _a.toISOString()}, and renewing it on a later run.`, certLogAttributes);
|
|
431
|
+
await CertificateOrderFailures.record({
|
|
432
|
+
domain: domain,
|
|
433
|
+
error: `We could not renew the certificate of ${lock.domain} because its CNAME record could not be verified. The certificate keeps serving until it expires; please check that the record still points to OneUptime.`,
|
|
434
|
+
now: now,
|
|
435
|
+
});
|
|
436
|
+
return;
|
|
437
|
+
}
|
|
438
|
+
logger.debug(`CNAME of ${domain} did not validate and its certificate has expired: removing the certificate.`, certLogAttributes);
|
|
114
439
|
await GreenlockUtil.removeDomain(domain);
|
|
115
440
|
await data.notifyDomainRemoved(domain);
|
|
116
|
-
|
|
117
|
-
}
|
|
118
|
-
else {
|
|
119
|
-
logger.debug(`CNAME is valid for domain: ${domain}`, certLogAttributes);
|
|
120
|
-
await GreenlockUtil.orderCert({
|
|
121
|
-
domain: domain,
|
|
122
|
-
validateCname: data.validateCname,
|
|
123
|
-
});
|
|
124
|
-
logger.debug(`Certificate renewed for domain: ${domain}`, certLogAttributes);
|
|
441
|
+
return;
|
|
125
442
|
}
|
|
443
|
+
logger.debug(`CNAME is valid for domain: ${domain}`, certLogAttributes);
|
|
444
|
+
const outcome = await GreenlockUtil.orderCert({
|
|
445
|
+
domain: domain,
|
|
446
|
+
reason: CertificateOrderReason.Renewal,
|
|
447
|
+
// Checked a moment ago, above.
|
|
448
|
+
validateCname: null,
|
|
449
|
+
lock: lock,
|
|
450
|
+
});
|
|
451
|
+
logger.debug(outcome === CertificateOrderOutcome.Ordered
|
|
452
|
+
? `Certificate renewed for domain: ${domain}`
|
|
453
|
+
: `Certificate of ${domain} not renewed now (${outcome}): a later run renews it.`, certLogAttributes);
|
|
126
454
|
}
|
|
127
455
|
catch (e) {
|
|
128
456
|
logger.error(`Error renewing certificate for domain: ${domain}`, certLogAttributes);
|
|
129
457
|
logger.error(e, certLogAttributes);
|
|
130
458
|
}
|
|
459
|
+
finally {
|
|
460
|
+
await CertificateOrderLock.release(lock);
|
|
461
|
+
}
|
|
131
462
|
}
|
|
132
463
|
static async removeDomain(domain) {
|
|
133
464
|
try {
|
|
@@ -148,151 +479,236 @@ class GreenlockUtil {
|
|
|
148
479
|
throw err;
|
|
149
480
|
}
|
|
150
481
|
}
|
|
482
|
+
/*
|
|
483
|
+
* Order a certificate for a name from Let's Encrypt and store it. Every
|
|
484
|
+
* certificate this installation orders is ordered here, whoever asks -
|
|
485
|
+
* Check now, the sweeps, the order and reissue APIs, the renewal runs and
|
|
486
|
+
* CoreSSL - so what must hold for every order holds here:
|
|
487
|
+
*
|
|
488
|
+
* - One order per name at a time. The order runs under the name's lock
|
|
489
|
+
* (CertificateOrderLock): the one the caller hands in, or one taken
|
|
490
|
+
* here. A name whose lock is taken is not ordered (NotOrderedNow).
|
|
491
|
+
* - The installation's Let's Encrypt allowance. Each order takes one unit
|
|
492
|
+
* of CertificateOrderBudget for its reason, and none is placed when
|
|
493
|
+
* there is none left (LimitReached).
|
|
494
|
+
* - Nothing is deleted. A CNAME check that fails refuses the order and
|
|
495
|
+
* leaves the name's certificate as it is. It used to remove it, so a
|
|
496
|
+
* DNS blip during a reissue, a renewal or a dashboard order took a
|
|
497
|
+
* working domain off HTTPS.
|
|
498
|
+
* - A failed order is recorded (CertificateOrderFailures) for the
|
|
499
|
+
* domain's Status column and the retry delay of the sweeps, and a
|
|
500
|
+
* successful one clears that record.
|
|
501
|
+
*
|
|
502
|
+
* Throws when the CNAME check fails or the order fails, with a message the
|
|
503
|
+
* caller can show.
|
|
504
|
+
*/
|
|
151
505
|
static async orderCert(data) {
|
|
152
|
-
const
|
|
153
|
-
|
|
154
|
-
|
|
506
|
+
const domain = CertificateOrderLock.normalizeDomain(data.domain);
|
|
507
|
+
if (data.lock && !CertificateOrderLock.isHeldFor(data.lock, domain)) {
|
|
508
|
+
/*
|
|
509
|
+
* Redis lost the lock while the caller held it: another order of the
|
|
510
|
+
* name may be running now. Not the caller's mistake - just not now.
|
|
511
|
+
*/
|
|
512
|
+
if (CertificateOrderLock.wasLost(data.lock, domain)) {
|
|
513
|
+
logger.debug(`Not ordering a certificate for ${domain}: the lock on the name was lost before the order`, { domain: domain });
|
|
514
|
+
return CertificateOrderOutcome.NotOrderedNow;
|
|
515
|
+
}
|
|
516
|
+
throw new BadDataException(`The certificate order lock handed in for ${domain} is not held.`);
|
|
517
|
+
}
|
|
518
|
+
const lock = data.lock || (await CertificateOrderLock.tryLock(domain));
|
|
519
|
+
if (!lock) {
|
|
520
|
+
return CertificateOrderOutcome.NotOrderedNow;
|
|
521
|
+
}
|
|
155
522
|
try {
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
523
|
+
return await GreenlockUtil.orderCertWithLockHeld({
|
|
524
|
+
domain: domain,
|
|
525
|
+
reason: data.reason,
|
|
526
|
+
validateCname: data.validateCname,
|
|
527
|
+
mayOrder: data.mayOrder,
|
|
528
|
+
});
|
|
529
|
+
}
|
|
530
|
+
finally {
|
|
531
|
+
if (!data.lock) {
|
|
532
|
+
await CertificateOrderLock.release(lock);
|
|
163
533
|
}
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
static async orderCertWithLockHeld(data) {
|
|
537
|
+
const { domain } = data;
|
|
538
|
+
const orderLogAttributes = {
|
|
539
|
+
domain: domain,
|
|
540
|
+
};
|
|
541
|
+
logger.debug(`GreenlockUtil - Ordering certificate for domain: ${domain} (${data.reason})`, orderLogAttributes);
|
|
542
|
+
if (data.validateCname) {
|
|
167
543
|
logger.debug(`Validating cname for domain: ${domain}`, orderLogAttributes);
|
|
168
544
|
const isValidCname = await data.validateCname(domain);
|
|
169
545
|
if (!isValidCname) {
|
|
170
|
-
logger.
|
|
171
|
-
logger.debug(`Removing domain: ${domain}`, orderLogAttributes);
|
|
172
|
-
await GreenlockUtil.removeDomain(domain);
|
|
173
|
-
logger.error(`Cname is not valid for domain: ${domain}`, orderLogAttributes);
|
|
546
|
+
logger.error(`Cname is not valid for domain: ${domain}. Not ordering, and keeping its certificate, if it has one.`, orderLogAttributes);
|
|
174
547
|
throw new BadDataException("Cname is not valid for domain " + domain);
|
|
175
548
|
}
|
|
176
549
|
logger.debug(`Cname is valid for domain: ${domain}`, orderLogAttributes);
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
550
|
+
}
|
|
551
|
+
if (data.mayOrder && !(await data.mayOrder())) {
|
|
552
|
+
logger.debug(`Not ordering a certificate for ${domain} now: this window's orders of its kind are used up`, orderLogAttributes);
|
|
553
|
+
return CertificateOrderOutcome.LimitReached;
|
|
554
|
+
}
|
|
555
|
+
try {
|
|
556
|
+
const acmeAccountKeyInBase64 = LetsEncryptAccountKey;
|
|
557
|
+
if (!acmeAccountKeyInBase64) {
|
|
558
|
+
throw new ServerException("No lets encrypt account key found in environment variables. Please add one.");
|
|
559
|
+
}
|
|
560
|
+
if (!(await CertificateOrderBudget.takeSlot({
|
|
561
|
+
reason: data.reason,
|
|
562
|
+
now: OneUptimeDate.getCurrentDate(),
|
|
563
|
+
domain: domain,
|
|
564
|
+
}))) {
|
|
565
|
+
return CertificateOrderOutcome.LimitReached;
|
|
566
|
+
}
|
|
567
|
+
await GreenlockUtil.orderAndStoreCertificate({
|
|
568
|
+
domain: domain,
|
|
569
|
+
acmeAccountKeyInBase64: acmeAccountKeyInBase64,
|
|
570
|
+
orderLogAttributes: orderLogAttributes,
|
|
183
571
|
});
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
if (challenge.type === "http-01") {
|
|
194
|
-
logger.debug(`Creating challenge for domain: ${authz.identifier.value}`, orderLogAttributes);
|
|
195
|
-
const acmeChallenge = new AcmeChallenge();
|
|
196
|
-
acmeChallenge.challenge = keyAuthorization;
|
|
197
|
-
acmeChallenge.token = challenge.token;
|
|
198
|
-
acmeChallenge.domain = authz.identifier.value;
|
|
199
|
-
await AcmeChallengeService.create({
|
|
200
|
-
data: acmeChallenge,
|
|
201
|
-
props: {
|
|
202
|
-
isRoot: true,
|
|
203
|
-
},
|
|
204
|
-
});
|
|
205
|
-
logger.debug(`Challenge created for domain: ${authz.identifier.value}`, orderLogAttributes);
|
|
206
|
-
}
|
|
207
|
-
},
|
|
208
|
-
challengeRemoveFn: async (authz, challenge) => {
|
|
209
|
-
// Clean up challenge here
|
|
210
|
-
logger.debug(`Removing challenge for domain: ${authz.identifier.value}`, orderLogAttributes);
|
|
211
|
-
if (challenge.type === "http-01") {
|
|
212
|
-
await AcmeChallengeService.deleteBy({
|
|
213
|
-
query: {
|
|
214
|
-
domain: authz.identifier.value,
|
|
215
|
-
},
|
|
216
|
-
limit: 1,
|
|
217
|
-
skip: 0,
|
|
218
|
-
props: {
|
|
219
|
-
isRoot: true,
|
|
220
|
-
},
|
|
221
|
-
});
|
|
222
|
-
}
|
|
223
|
-
logger.debug(`Challenge removed for domain: ${authz.identifier.value}`, orderLogAttributes);
|
|
224
|
-
},
|
|
572
|
+
}
|
|
573
|
+
catch (e) {
|
|
574
|
+
logger.error(`Error ordering certificate for domain: ${domain}`, orderLogAttributes);
|
|
575
|
+
logger.error(e, orderLogAttributes);
|
|
576
|
+
const error = GreenlockUtil.toOrderError(e, domain);
|
|
577
|
+
await CertificateOrderFailures.record({
|
|
578
|
+
domain: domain,
|
|
579
|
+
error: error.message,
|
|
580
|
+
now: OneUptimeDate.getCurrentDate(),
|
|
225
581
|
});
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
582
|
+
throw error;
|
|
583
|
+
}
|
|
584
|
+
await CertificateOrderFailures.clear(domain);
|
|
585
|
+
return CertificateOrderOutcome.Ordered;
|
|
586
|
+
}
|
|
587
|
+
// What the caller of a failed order is told.
|
|
588
|
+
static toOrderError(e, domain) {
|
|
589
|
+
if (e instanceof Exception) {
|
|
590
|
+
return e;
|
|
591
|
+
}
|
|
592
|
+
if (IsBillingEnabled) {
|
|
593
|
+
return new ServerException(`Unable to order certificate for ${domain}. Please contact support at support@oneuptime.com for more information.`);
|
|
594
|
+
}
|
|
595
|
+
return new ServerException(`Unable to order certificate for ${domain}. Please make sure that your server can be accessed publicly over port 80 (HTTP) and port 443 (HTTPS). If the problem persists, please refer to server logs for more information. Please also set up LOG_LEVEL=DEBUG to get more detailed server logs.`);
|
|
596
|
+
}
|
|
597
|
+
static async orderAndStoreCertificate(data) {
|
|
598
|
+
const { domain, orderLogAttributes } = data;
|
|
599
|
+
let acmeAccountKey = Buffer.from(data.acmeAccountKeyInBase64, "base64").toString();
|
|
600
|
+
acmeAccountKey = Text.replaceAll(acmeAccountKey, "\\n", "\n");
|
|
601
|
+
const client = new acme.Client({
|
|
602
|
+
directoryUrl: acme.directory.letsencrypt.production,
|
|
603
|
+
accountKey: acmeAccountKey,
|
|
604
|
+
});
|
|
605
|
+
const [certificateKey, certificateRequest] = await acme.crypto.createCsr({
|
|
606
|
+
commonName: domain,
|
|
607
|
+
});
|
|
608
|
+
logger.debug(`Ordering certificate for domain: ${domain}`, orderLogAttributes);
|
|
609
|
+
const certificate = await client.auto({
|
|
610
|
+
csr: certificateRequest,
|
|
611
|
+
email: LetsEncryptNotificationEmail.toString(),
|
|
612
|
+
termsOfServiceAgreed: true,
|
|
613
|
+
challengePriority: ["http-01"], // only http-01 challenge is supported by oneuptime
|
|
614
|
+
challengeCreateFn: async (authz, challenge, keyAuthorization) => {
|
|
615
|
+
// Satisfy challenge here
|
|
616
|
+
/* http-01 */
|
|
617
|
+
if (challenge.type === "http-01") {
|
|
618
|
+
logger.debug(`Creating challenge for domain: ${authz.identifier.value}`, orderLogAttributes);
|
|
619
|
+
const acmeChallenge = new AcmeChallenge();
|
|
620
|
+
acmeChallenge.challenge = keyAuthorization;
|
|
621
|
+
acmeChallenge.token = challenge.token;
|
|
622
|
+
acmeChallenge.domain = authz.identifier.value;
|
|
623
|
+
await AcmeChallengeService.create({
|
|
624
|
+
data: acmeChallenge,
|
|
625
|
+
props: {
|
|
626
|
+
isRoot: true,
|
|
627
|
+
},
|
|
628
|
+
});
|
|
629
|
+
logger.debug(`Challenge created for domain: ${authz.identifier.value}`, orderLogAttributes);
|
|
630
|
+
}
|
|
631
|
+
},
|
|
632
|
+
challengeRemoveFn: async (authz, challenge) => {
|
|
633
|
+
// Clean up challenge here
|
|
634
|
+
logger.debug(`Removing challenge for domain: ${authz.identifier.value}`, orderLogAttributes);
|
|
635
|
+
if (challenge.type === "http-01") {
|
|
636
|
+
await AcmeChallengeService.deleteBy({
|
|
637
|
+
query: {
|
|
638
|
+
domain: authz.identifier.value,
|
|
639
|
+
},
|
|
640
|
+
limit: 1,
|
|
641
|
+
skip: 0,
|
|
642
|
+
props: {
|
|
643
|
+
isRoot: true,
|
|
644
|
+
},
|
|
645
|
+
});
|
|
646
|
+
}
|
|
647
|
+
logger.debug(`Challenge removed for domain: ${authz.identifier.value}`, orderLogAttributes);
|
|
648
|
+
},
|
|
649
|
+
});
|
|
650
|
+
logger.debug(`Certificate ordered for domain: ${domain}`, orderLogAttributes);
|
|
651
|
+
// get expires at date from certificate
|
|
652
|
+
const cert = acme.crypto.readCertificateInfo(certificate);
|
|
653
|
+
const issuedAt = cert.notBefore;
|
|
654
|
+
const expiresAt = cert.notAfter;
|
|
655
|
+
logger.debug(`Certificate expires at: ${expiresAt}`, orderLogAttributes);
|
|
656
|
+
logger.debug(`Certificate issued at: ${issuedAt}`, orderLogAttributes);
|
|
657
|
+
// check if the certificate is already in the database.
|
|
658
|
+
const existingCertificate = await AcmeCertificateService.findOneBy({
|
|
659
|
+
query: {
|
|
660
|
+
domain: domain,
|
|
661
|
+
},
|
|
662
|
+
select: {
|
|
663
|
+
_id: true,
|
|
664
|
+
},
|
|
665
|
+
props: {
|
|
666
|
+
isRoot: true,
|
|
667
|
+
},
|
|
668
|
+
});
|
|
669
|
+
/*
|
|
670
|
+
* The row can be removed between the look-up above and this write (a
|
|
671
|
+
* domain deleted meanwhile, or the cleanup of expired certificates
|
|
672
|
+
* nobody owned). Then the update finds nothing, and the certificate
|
|
673
|
+
* the CA has just issued is stored in a new row instead of being lost.
|
|
674
|
+
*/
|
|
675
|
+
const updatedCount = existingCertificate
|
|
676
|
+
? await AcmeCertificateService.updateBy({
|
|
235
677
|
query: {
|
|
236
678
|
domain: domain,
|
|
237
679
|
},
|
|
238
|
-
|
|
239
|
-
|
|
680
|
+
limit: 1,
|
|
681
|
+
skip: 0,
|
|
682
|
+
data: {
|
|
683
|
+
certificate: certificate.toString(),
|
|
684
|
+
certificateKey: certificateKey.toString(),
|
|
685
|
+
issuedAt: issuedAt,
|
|
686
|
+
expiresAt: expiresAt,
|
|
240
687
|
},
|
|
241
688
|
props: {
|
|
242
689
|
isRoot: true,
|
|
243
690
|
},
|
|
244
|
-
})
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
await AcmeCertificateService.updateBy({
|
|
249
|
-
query: {
|
|
250
|
-
domain: domain,
|
|
251
|
-
},
|
|
252
|
-
limit: 1,
|
|
253
|
-
skip: 0,
|
|
254
|
-
data: {
|
|
255
|
-
certificate: certificate.toString(),
|
|
256
|
-
certificateKey: certificateKey.toString(),
|
|
257
|
-
issuedAt: issuedAt,
|
|
258
|
-
expiresAt: expiresAt,
|
|
259
|
-
},
|
|
260
|
-
props: {
|
|
261
|
-
isRoot: true,
|
|
262
|
-
},
|
|
263
|
-
});
|
|
264
|
-
logger.debug(`Certificate updated for domain: ${domain}`, orderLogAttributes);
|
|
265
|
-
}
|
|
266
|
-
else {
|
|
267
|
-
logger.debug(`Creating certificate for domain: ${domain}`, orderLogAttributes);
|
|
268
|
-
// create the certificate
|
|
269
|
-
const acmeCertificate = new AcmeCertificate();
|
|
270
|
-
acmeCertificate.domain = domain;
|
|
271
|
-
acmeCertificate.certificate = certificate.toString();
|
|
272
|
-
acmeCertificate.certificateKey = certificateKey.toString();
|
|
273
|
-
acmeCertificate.issuedAt = issuedAt;
|
|
274
|
-
acmeCertificate.expiresAt = expiresAt;
|
|
275
|
-
await AcmeCertificateService.create({
|
|
276
|
-
data: acmeCertificate,
|
|
277
|
-
props: {
|
|
278
|
-
isRoot: true,
|
|
279
|
-
},
|
|
280
|
-
});
|
|
281
|
-
logger.debug(`Certificate created for domain: ${domain}`, orderLogAttributes);
|
|
282
|
-
}
|
|
691
|
+
})
|
|
692
|
+
: 0;
|
|
693
|
+
if (updatedCount > 0) {
|
|
694
|
+
logger.debug(`Certificate updated for domain: ${domain}`, orderLogAttributes);
|
|
283
695
|
}
|
|
284
|
-
|
|
285
|
-
logger.
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
696
|
+
else {
|
|
697
|
+
logger.debug(`Creating certificate for domain: ${domain}`, orderLogAttributes);
|
|
698
|
+
// create the certificate
|
|
699
|
+
const acmeCertificate = new AcmeCertificate();
|
|
700
|
+
acmeCertificate.domain = domain;
|
|
701
|
+
acmeCertificate.certificate = certificate.toString();
|
|
702
|
+
acmeCertificate.certificateKey = certificateKey.toString();
|
|
703
|
+
acmeCertificate.issuedAt = issuedAt;
|
|
704
|
+
acmeCertificate.expiresAt = expiresAt;
|
|
705
|
+
await AcmeCertificateService.create({
|
|
706
|
+
data: acmeCertificate,
|
|
707
|
+
props: {
|
|
708
|
+
isRoot: true,
|
|
709
|
+
},
|
|
710
|
+
});
|
|
711
|
+
logger.debug(`Certificate created for domain: ${domain}`, orderLogAttributes);
|
|
296
712
|
}
|
|
297
713
|
}
|
|
298
714
|
}
|
|
@@ -326,13 +742,46 @@ GreenlockUtil.RENEW_LEAD_TIME_MIN_IN_DAYS = 25;
|
|
|
326
742
|
*/
|
|
327
743
|
GreenlockUtil.RENEW_MAX_PER_RUN = 10;
|
|
328
744
|
GreenlockUtil.RENEW_CONCURRENCY = 5;
|
|
745
|
+
/*
|
|
746
|
+
* Lookups by domain name (an owner asked which domains are its own, the
|
|
747
|
+
* certificates of a list of domains) take at most this many names at once,
|
|
748
|
+
* so a long list becomes several short IN (...) lookups rather than one
|
|
749
|
+
* statement with thousands of parameters.
|
|
750
|
+
*/
|
|
751
|
+
GreenlockUtil.DOMAIN_LOOKUP_CHUNK_SIZE = 500;
|
|
752
|
+
/*
|
|
753
|
+
* A certificate nobody owns is deleted once it has been expired this long,
|
|
754
|
+
* at most REMOVE_UNOWNED_MAX_PER_RUN per run.
|
|
755
|
+
*
|
|
756
|
+
* Such certificates are left behind when a project, status page, dashboard
|
|
757
|
+
* or parent domain is deleted: those deletes remove the domain rows through
|
|
758
|
+
* the database's ON DELETE CASCADE, which skips the hook that removes the
|
|
759
|
+
* certificate. An expired certificate serves nobody, and every owner orders
|
|
760
|
+
* a fresh one when its own is missing, so deleting one cannot take a
|
|
761
|
+
* working domain down. The month of grace is for a domain that is deleted
|
|
762
|
+
* and added back.
|
|
763
|
+
*/
|
|
764
|
+
GreenlockUtil.REMOVE_UNOWNED_AFTER_EXPIRY_IN_DAYS = 30;
|
|
765
|
+
GreenlockUtil.REMOVE_UNOWNED_MAX_PER_RUN = 100;
|
|
329
766
|
export default GreenlockUtil;
|
|
767
|
+
__decorate([
|
|
768
|
+
CaptureSpan(),
|
|
769
|
+
__metadata("design:type", Function),
|
|
770
|
+
__metadata("design:paramtypes", [Array]),
|
|
771
|
+
__metadata("design:returntype", Promise)
|
|
772
|
+
], GreenlockUtil, "findCertificatesByDomain", null);
|
|
330
773
|
__decorate([
|
|
331
774
|
CaptureSpan(),
|
|
332
775
|
__metadata("design:type", Function),
|
|
333
776
|
__metadata("design:paramtypes", [Object]),
|
|
334
777
|
__metadata("design:returntype", Promise)
|
|
335
778
|
], GreenlockUtil, "renewAllCertsWhichAreExpiringSoon", null);
|
|
779
|
+
__decorate([
|
|
780
|
+
CaptureSpan(),
|
|
781
|
+
__metadata("design:type", Function),
|
|
782
|
+
__metadata("design:paramtypes", [Object]),
|
|
783
|
+
__metadata("design:returntype", Promise)
|
|
784
|
+
], GreenlockUtil, "removeExpiredCertificatesNobodyOwns", null);
|
|
336
785
|
__decorate([
|
|
337
786
|
CaptureSpan(),
|
|
338
787
|
__metadata("design:type", Function),
|