@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
|
@@ -8,7 +8,6 @@ import AcmeChallengeService from "../../Services/AcmeChallengeService";
|
|
|
8
8
|
import QueryHelper from "../../Types/Database/QueryHelper";
|
|
9
9
|
import logger, { LogAttributes } from "../Logger";
|
|
10
10
|
import SortOrder from "../../../Types/BaseDatabase/SortOrder";
|
|
11
|
-
import LIMIT_MAX from "../../../Types/Database/LimitMax";
|
|
12
11
|
import OneUptimeDate from "../../../Types/Date";
|
|
13
12
|
import BadDataException from "../../../Types/Exception/BadDataException";
|
|
14
13
|
import Exception from "../../../Types/Exception/Exception";
|
|
@@ -16,10 +15,19 @@ import ServerException from "../../../Types/Exception/ServerException";
|
|
|
16
15
|
import Text from "../../../Types/Text";
|
|
17
16
|
import AcmeCertificate from "../../../Models/DatabaseModels/AcmeCertificate";
|
|
18
17
|
import AcmeChallenge from "../../../Models/DatabaseModels/AcmeChallenge";
|
|
18
|
+
import LIMIT_MAX from "../../../Types/Database/LimitMax";
|
|
19
19
|
import ArrayUtil from "../../../Utils/Array";
|
|
20
20
|
import acme from "acme-client";
|
|
21
21
|
import { Challenge } from "acme-client/types/rfc8555";
|
|
22
22
|
import CaptureSpan from "../Telemetry/CaptureSpan";
|
|
23
|
+
import CertificateOrderLock, {
|
|
24
|
+
CertificateOrderLockHandle,
|
|
25
|
+
} from "./CertificateOrderLock";
|
|
26
|
+
import CertificateOrderBudget, {
|
|
27
|
+
CertificateOrderReason,
|
|
28
|
+
} from "./CertificateOrderBudget";
|
|
29
|
+
import CertificateOrderFailures from "./CertificateOrderFailures";
|
|
30
|
+
import { CertificateOrderOutcome } from "./CertificateOrderOutcome";
|
|
23
31
|
|
|
24
32
|
export default class GreenlockUtil {
|
|
25
33
|
/*
|
|
@@ -54,6 +62,29 @@ export default class GreenlockUtil {
|
|
|
54
62
|
public static readonly RENEW_MAX_PER_RUN: number = 10;
|
|
55
63
|
public static readonly RENEW_CONCURRENCY: number = 5;
|
|
56
64
|
|
|
65
|
+
/*
|
|
66
|
+
* Lookups by domain name (an owner asked which domains are its own, the
|
|
67
|
+
* certificates of a list of domains) take at most this many names at once,
|
|
68
|
+
* so a long list becomes several short IN (...) lookups rather than one
|
|
69
|
+
* statement with thousands of parameters.
|
|
70
|
+
*/
|
|
71
|
+
public static readonly DOMAIN_LOOKUP_CHUNK_SIZE: number = 500;
|
|
72
|
+
|
|
73
|
+
/*
|
|
74
|
+
* A certificate nobody owns is deleted once it has been expired this long,
|
|
75
|
+
* at most REMOVE_UNOWNED_MAX_PER_RUN per run.
|
|
76
|
+
*
|
|
77
|
+
* Such certificates are left behind when a project, status page, dashboard
|
|
78
|
+
* or parent domain is deleted: those deletes remove the domain rows through
|
|
79
|
+
* the database's ON DELETE CASCADE, which skips the hook that removes the
|
|
80
|
+
* certificate. An expired certificate serves nobody, and every owner orders
|
|
81
|
+
* a fresh one when its own is missing, so deleting one cannot take a
|
|
82
|
+
* working domain down. The month of grace is for a domain that is deleted
|
|
83
|
+
* and added back.
|
|
84
|
+
*/
|
|
85
|
+
public static readonly REMOVE_UNOWNED_AFTER_EXPIRY_IN_DAYS: number = 30;
|
|
86
|
+
public static readonly REMOVE_UNOWNED_MAX_PER_RUN: number = 100;
|
|
87
|
+
|
|
57
88
|
/*
|
|
58
89
|
* Stable per-domain lead time, somewhere in the range above. Same domain,
|
|
59
90
|
* same answer, on every run and every replica.
|
|
@@ -74,10 +105,224 @@ export default class GreenlockUtil {
|
|
|
74
105
|
);
|
|
75
106
|
}
|
|
76
107
|
|
|
108
|
+
/*
|
|
109
|
+
* Whether this certificate has reached its own renewal lead time. Expired
|
|
110
|
+
* certificates are due too.
|
|
111
|
+
*/
|
|
112
|
+
public static isDueForRenewal(
|
|
113
|
+
certificate: { domain?: string | undefined; expiresAt?: Date | undefined },
|
|
114
|
+
now: Date,
|
|
115
|
+
): boolean {
|
|
116
|
+
if (!certificate.domain || !certificate.expiresAt) {
|
|
117
|
+
return false;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const renewAt: Date = OneUptimeDate.addRemoveDays(
|
|
121
|
+
certificate.expiresAt,
|
|
122
|
+
-GreenlockUtil.getRenewalLeadTimeInDays(certificate.domain),
|
|
123
|
+
);
|
|
124
|
+
|
|
125
|
+
return !OneUptimeDate.isAfter(renewAt, now);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/*
|
|
129
|
+
* The items a capped sweep works on in this run: at most max of them,
|
|
130
|
+
* chosen by a shuffle that is the same for every replica within one
|
|
131
|
+
* 15-minute window and different in the next, so an item whose work keeps
|
|
132
|
+
* failing cannot hold a slot run after run while the others wait. Every
|
|
133
|
+
* item has the same chance in every run, however the list grows, shrinks
|
|
134
|
+
* or is ordered, and whatever schedule the sweep runs on - a fixed
|
|
135
|
+
* rotation would skip items whenever earlier ones left the list.
|
|
136
|
+
*/
|
|
137
|
+
public static pickForThisRun<T>(data: {
|
|
138
|
+
items: Array<T>;
|
|
139
|
+
max: number;
|
|
140
|
+
now: Date;
|
|
141
|
+
getKey: (item: T) => string;
|
|
142
|
+
}): Array<T> {
|
|
143
|
+
const max: number = Math.max(Math.floor(data.max), 0);
|
|
144
|
+
|
|
145
|
+
const window: number = Math.floor(
|
|
146
|
+
data.now.getTime() / OneUptimeDate.convertMinutesToMilliseconds(15),
|
|
147
|
+
);
|
|
148
|
+
|
|
149
|
+
return data.items
|
|
150
|
+
.map((item: T) => {
|
|
151
|
+
const key: string = data.getKey(item);
|
|
152
|
+
|
|
153
|
+
return {
|
|
154
|
+
item: item,
|
|
155
|
+
key: key,
|
|
156
|
+
rank:
|
|
157
|
+
data.items.length <= max
|
|
158
|
+
? 0
|
|
159
|
+
: GreenlockUtil.hashText(`${window}:${key}`),
|
|
160
|
+
};
|
|
161
|
+
})
|
|
162
|
+
.sort(
|
|
163
|
+
(
|
|
164
|
+
a: { key: string; rank: number },
|
|
165
|
+
b: { key: string; rank: number },
|
|
166
|
+
) => {
|
|
167
|
+
if (a.rank !== b.rank) {
|
|
168
|
+
return a.rank - b.rank;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if (a.key === b.key) {
|
|
172
|
+
return 0;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
return a.key < b.key ? -1 : 1;
|
|
176
|
+
},
|
|
177
|
+
)
|
|
178
|
+
.slice(0, max)
|
|
179
|
+
.map((ranked: { item: T }) => {
|
|
180
|
+
return ranked.item;
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// 32-bit FNV-1a: a stable, well-spread hash of a string.
|
|
185
|
+
private static hashText(text: string): number {
|
|
186
|
+
let hash: number = 0x811c9dc5;
|
|
187
|
+
|
|
188
|
+
for (let i: number = 0; i < text.length; i++) {
|
|
189
|
+
hash ^= text.charCodeAt(i);
|
|
190
|
+
hash = Math.imul(hash, 0x01000193) >>> 0;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
return hash;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/*
|
|
197
|
+
* The certificate each of these domains has in AcmeCertificate, if any,
|
|
198
|
+
* looked up DOMAIN_LOOKUP_CHUNK_SIZE names at a time. Where a name has more
|
|
199
|
+
* than one row, the one that expires last. A row without an expiry is no
|
|
200
|
+
* certificate at all: it is never due, so nothing would ever replace it if
|
|
201
|
+
* it counted as one.
|
|
202
|
+
*
|
|
203
|
+
* The sweeps that order first certificates and re-order missing ones read
|
|
204
|
+
* this to tell a domain that needs an order from one that only needs to be
|
|
205
|
+
* recorded as ordered.
|
|
206
|
+
*/
|
|
207
|
+
@CaptureSpan()
|
|
208
|
+
public static async findCertificatesByDomain(
|
|
209
|
+
domains: Array<string>,
|
|
210
|
+
): Promise<Map<string, AcmeCertificate>> {
|
|
211
|
+
const certificates: Map<string, AcmeCertificate> = new Map<
|
|
212
|
+
string,
|
|
213
|
+
AcmeCertificate
|
|
214
|
+
>();
|
|
215
|
+
|
|
216
|
+
const uniqueDomains: Array<string> = Array.from(
|
|
217
|
+
new Set<string>(
|
|
218
|
+
domains.filter((domain: string) => {
|
|
219
|
+
return domain.length > 0;
|
|
220
|
+
}),
|
|
221
|
+
),
|
|
222
|
+
);
|
|
223
|
+
|
|
224
|
+
for (
|
|
225
|
+
let offset: number = 0;
|
|
226
|
+
offset < uniqueDomains.length;
|
|
227
|
+
offset += GreenlockUtil.DOMAIN_LOOKUP_CHUNK_SIZE
|
|
228
|
+
) {
|
|
229
|
+
const chunk: Array<string> = uniqueDomains.slice(
|
|
230
|
+
offset,
|
|
231
|
+
offset + GreenlockUtil.DOMAIN_LOOKUP_CHUNK_SIZE,
|
|
232
|
+
);
|
|
233
|
+
|
|
234
|
+
const rows: Array<AcmeCertificate> = await AcmeCertificateService.findBy({
|
|
235
|
+
query: {
|
|
236
|
+
domain: QueryHelper.any(chunk),
|
|
237
|
+
},
|
|
238
|
+
select: {
|
|
239
|
+
domain: true,
|
|
240
|
+
expiresAt: true,
|
|
241
|
+
},
|
|
242
|
+
limit: LIMIT_MAX,
|
|
243
|
+
skip: 0,
|
|
244
|
+
props: {
|
|
245
|
+
isRoot: true,
|
|
246
|
+
},
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
for (const row of rows) {
|
|
250
|
+
if (!row.domain || !row.expiresAt) {
|
|
251
|
+
continue;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
const existing: AcmeCertificate | undefined = certificates.get(
|
|
255
|
+
row.domain,
|
|
256
|
+
);
|
|
257
|
+
|
|
258
|
+
if (
|
|
259
|
+
!existing ||
|
|
260
|
+
OneUptimeDate.isAfter(row.expiresAt, existing.expiresAt as Date)
|
|
261
|
+
) {
|
|
262
|
+
certificates.set(row.domain, row);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
return certificates;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/*
|
|
271
|
+
* Ask one owner which of these domains are its own, a chunk at a time.
|
|
272
|
+
*/
|
|
273
|
+
private static async getOwnedAmong(data: {
|
|
274
|
+
domains: Array<string>;
|
|
275
|
+
getOwnedDomains: (domains: Array<string>) => Promise<Array<string>>;
|
|
276
|
+
}): Promise<Set<string>> {
|
|
277
|
+
const owned: Set<string> = new Set<string>();
|
|
278
|
+
const domains: Array<string> = Array.from(new Set<string>(data.domains));
|
|
279
|
+
|
|
280
|
+
for (
|
|
281
|
+
let offset: number = 0;
|
|
282
|
+
offset < domains.length;
|
|
283
|
+
offset += GreenlockUtil.DOMAIN_LOOKUP_CHUNK_SIZE
|
|
284
|
+
) {
|
|
285
|
+
const chunk: Array<string> = domains.slice(
|
|
286
|
+
offset,
|
|
287
|
+
offset + GreenlockUtil.DOMAIN_LOOKUP_CHUNK_SIZE,
|
|
288
|
+
);
|
|
289
|
+
|
|
290
|
+
for (const domain of await data.getOwnedDomains(chunk)) {
|
|
291
|
+
owned.add(domain);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
return owned;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/*
|
|
299
|
+
* Renew the caller's certificates that are due, at most maxPerRun of them
|
|
300
|
+
* per run (RENEW_MAX_PER_RUN unless the caller asks for fewer).
|
|
301
|
+
*
|
|
302
|
+
* AcmeCertificate is one table shared by every owner of a certificate:
|
|
303
|
+
* status page domains, dashboard domains and the installation's own
|
|
304
|
+
* primary host (CoreSSL). Each owner runs this on its own schedule and can
|
|
305
|
+
* only judge its own domains - its validateCname reports false for every
|
|
306
|
+
* domain it has no row for. So a run must never act on a certificate it
|
|
307
|
+
* does not own. Before getOwnedDomains existed, the status page run
|
|
308
|
+
* treated every dashboard certificate (and the primary host's, whenever
|
|
309
|
+
* its lead time came before CoreSSL's 30-day renewal) as a status page
|
|
310
|
+
* whose CNAME had stopped validating, and deleted it.
|
|
311
|
+
*
|
|
312
|
+
* getOwnedDomains is handed the due domains (a chunk at a time) and
|
|
313
|
+
* returns the ones the caller owns. Every due certificate is read, not a
|
|
314
|
+
* first page of them, and ownership is settled before the cap, so neither
|
|
315
|
+
* another owner's backlog nor a pile of expired certificates nobody owns
|
|
316
|
+
* can take this caller's slots. A certificate nobody claims is left exactly
|
|
317
|
+
* as it is: neither renewed nor removed
|
|
318
|
+
* (removeExpiredCertificatesNobodyOwns cleans those up once they are dead).
|
|
319
|
+
*/
|
|
77
320
|
@CaptureSpan()
|
|
78
321
|
public static async renewAllCertsWhichAreExpiringSoon(data: {
|
|
322
|
+
getOwnedDomains: (domains: Array<string>) => Promise<Array<string>>;
|
|
79
323
|
validateCname: (domain: string) => Promise<boolean>;
|
|
80
324
|
notifyDomainRemoved: (domain: string) => Promise<void>;
|
|
325
|
+
maxPerRun?: number | undefined;
|
|
81
326
|
}): Promise<void> {
|
|
82
327
|
try {
|
|
83
328
|
logger.debug("Renewing all certificates");
|
|
@@ -87,7 +332,7 @@ export default class GreenlockUtil {
|
|
|
87
332
|
* keep only the domains whose own lead time has actually been reached.
|
|
88
333
|
*/
|
|
89
334
|
const certificates: AcmeCertificate[] =
|
|
90
|
-
await AcmeCertificateService.
|
|
335
|
+
await AcmeCertificateService.findAllBy({
|
|
91
336
|
query: {
|
|
92
337
|
expiresAt: QueryHelper.lessThanEqualTo(
|
|
93
338
|
OneUptimeDate.addRemoveDays(
|
|
@@ -96,7 +341,6 @@ export default class GreenlockUtil {
|
|
|
96
341
|
),
|
|
97
342
|
),
|
|
98
343
|
},
|
|
99
|
-
limit: LIMIT_MAX,
|
|
100
344
|
skip: 0,
|
|
101
345
|
select: {
|
|
102
346
|
domain: true,
|
|
@@ -112,35 +356,115 @@ export default class GreenlockUtil {
|
|
|
112
356
|
|
|
113
357
|
const now: Date = OneUptimeDate.getCurrentDate();
|
|
114
358
|
|
|
359
|
+
/*
|
|
360
|
+
* One renewal per name: a name can have more than one row, and a row
|
|
361
|
+
* renewed between two page reads can come back on both.
|
|
362
|
+
*/
|
|
363
|
+
const dueDomains: Set<string> = new Set<string>();
|
|
364
|
+
|
|
115
365
|
const dueCertificates: AcmeCertificate[] = certificates.filter(
|
|
116
366
|
(certificate: AcmeCertificate) => {
|
|
117
|
-
if (
|
|
367
|
+
if (
|
|
368
|
+
!GreenlockUtil.isDueForRenewal(certificate, now) ||
|
|
369
|
+
dueDomains.has(certificate.domain as string)
|
|
370
|
+
) {
|
|
118
371
|
return false;
|
|
119
372
|
}
|
|
120
373
|
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
374
|
+
dueDomains.add(certificate.domain as string);
|
|
375
|
+
return true;
|
|
376
|
+
},
|
|
377
|
+
);
|
|
125
378
|
|
|
126
|
-
|
|
379
|
+
/*
|
|
380
|
+
* A lookup that fails throws out of the run before anything is renewed
|
|
381
|
+
* or removed: not knowing who owns a certificate is never a reason to
|
|
382
|
+
* touch it.
|
|
383
|
+
*/
|
|
384
|
+
const ownedDomains: Set<string> = await GreenlockUtil.getOwnedAmong({
|
|
385
|
+
domains: dueCertificates.map((certificate: AcmeCertificate) => {
|
|
386
|
+
return certificate.domain as string;
|
|
387
|
+
}),
|
|
388
|
+
getOwnedDomains: data.getOwnedDomains,
|
|
389
|
+
});
|
|
390
|
+
|
|
391
|
+
const ownedDueCertificates: AcmeCertificate[] = dueCertificates.filter(
|
|
392
|
+
(certificate: AcmeCertificate) => {
|
|
393
|
+
return ownedDomains.has(certificate.domain as string);
|
|
127
394
|
},
|
|
128
395
|
);
|
|
129
396
|
|
|
397
|
+
/*
|
|
398
|
+
* A name whose last renewals failed - a CAA record that leaves Let's
|
|
399
|
+
* Encrypt out, a name Let's Encrypt has paused - waits longer after
|
|
400
|
+
* each failure in a row (CertificateOrderFailures) instead of taking a
|
|
401
|
+
* slot in every run. Each failed order counts against the account all
|
|
402
|
+
* the same, and Let's Encrypt allows five failed validations per name
|
|
403
|
+
* per hour.
|
|
404
|
+
*/
|
|
405
|
+
const renewableDueCertificates: AcmeCertificate[] =
|
|
406
|
+
await CertificateOrderFailures.withoutThoseWaitingToRetry({
|
|
407
|
+
items: ownedDueCertificates,
|
|
408
|
+
getDomain: (certificate: AcmeCertificate): string => {
|
|
409
|
+
return certificate.domain as string;
|
|
410
|
+
},
|
|
411
|
+
now: now,
|
|
412
|
+
});
|
|
413
|
+
|
|
414
|
+
const maxPerRun: number = Math.max(
|
|
415
|
+
Math.min(
|
|
416
|
+
data.maxPerRun ?? GreenlockUtil.RENEW_MAX_PER_RUN,
|
|
417
|
+
GreenlockUtil.RENEW_MAX_PER_RUN,
|
|
418
|
+
),
|
|
419
|
+
0,
|
|
420
|
+
);
|
|
421
|
+
|
|
130
422
|
/*
|
|
131
423
|
* Still sorted by expiry, so a run that cannot take the whole backlog
|
|
132
424
|
* spends itself on the domains closest to expiring and leaves the rest -
|
|
133
425
|
* which by construction still have weeks of lead time - to the next run.
|
|
426
|
+
*
|
|
427
|
+
* Certificates that have already expired come after every one that can
|
|
428
|
+
* still be saved, and take turns among themselves. Such a domain has
|
|
429
|
+
* been failing to renew since its lead time began - a CAA record that
|
|
430
|
+
* leaves Let's Encrypt out, a name Let's Encrypt has paused - and,
|
|
431
|
+
* sorting first by expiry, it would otherwise take a slot in every run
|
|
432
|
+
* and starve the renewals behind it. It is still tried whenever slots
|
|
433
|
+
* are left, which in a run without a backlog is every run.
|
|
134
434
|
*/
|
|
135
|
-
const
|
|
136
|
-
|
|
137
|
-
|
|
435
|
+
const stillValid: AcmeCertificate[] = renewableDueCertificates.filter(
|
|
436
|
+
(certificate: AcmeCertificate) => {
|
|
437
|
+
return OneUptimeDate.isAfter(certificate.expiresAt as Date, now);
|
|
438
|
+
},
|
|
439
|
+
);
|
|
440
|
+
|
|
441
|
+
const alreadyExpired: AcmeCertificate[] = renewableDueCertificates.filter(
|
|
442
|
+
(certificate: AcmeCertificate) => {
|
|
443
|
+
return !OneUptimeDate.isAfter(certificate.expiresAt as Date, now);
|
|
444
|
+
},
|
|
138
445
|
);
|
|
139
446
|
|
|
447
|
+
const firstInLine: AcmeCertificate[] = stillValid.slice(0, maxPerRun);
|
|
448
|
+
|
|
449
|
+
const batch: AcmeCertificate[] = [
|
|
450
|
+
...firstInLine,
|
|
451
|
+
...GreenlockUtil.pickForThisRun({
|
|
452
|
+
items: alreadyExpired,
|
|
453
|
+
max: maxPerRun - firstInLine.length,
|
|
454
|
+
now: now,
|
|
455
|
+
getKey: (certificate: AcmeCertificate): string => {
|
|
456
|
+
return certificate.domain as string;
|
|
457
|
+
},
|
|
458
|
+
}),
|
|
459
|
+
];
|
|
460
|
+
|
|
140
461
|
logger.debug(
|
|
141
|
-
`Found ${dueCertificates.length} certificates due for renewal, renewing ${batch.length} in this run`,
|
|
462
|
+
`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`,
|
|
142
463
|
{
|
|
143
464
|
dueCount: dueCertificates.length,
|
|
465
|
+
ownedDueCount: ownedDueCertificates.length,
|
|
466
|
+
waitingAfterFailureCount:
|
|
467
|
+
ownedDueCertificates.length - renewableDueCertificates.length,
|
|
144
468
|
batchCount: batch.length,
|
|
145
469
|
},
|
|
146
470
|
);
|
|
@@ -164,10 +488,136 @@ export default class GreenlockUtil {
|
|
|
164
488
|
}
|
|
165
489
|
}
|
|
166
490
|
|
|
491
|
+
/*
|
|
492
|
+
* Delete certificates that have been expired for more than
|
|
493
|
+
* REMOVE_UNOWNED_AFTER_EXPIRY_IN_DAYS and that no owner claims, at most
|
|
494
|
+
* REMOVE_UNOWNED_MAX_PER_RUN per run. Returns how many were deleted.
|
|
495
|
+
*
|
|
496
|
+
* owners must name every kind of certificate owner there is (see
|
|
497
|
+
* CertificateOwners). A certificate is deleted only when all of them have
|
|
498
|
+
* answered and none claims it; if any lookup fails, nothing is deleted.
|
|
499
|
+
*
|
|
500
|
+
* The delete names the row's id AND that it is still expired, and
|
|
501
|
+
* hardDeleteBy keeps those conditions in the DELETE statement itself:
|
|
502
|
+
* orderCert renews a name by updating its row in place, so a row renewed at
|
|
503
|
+
* any point before the delete no longer matches and is kept. A newer row for
|
|
504
|
+
* the same name never matches either.
|
|
505
|
+
*/
|
|
506
|
+
@CaptureSpan()
|
|
507
|
+
public static async removeExpiredCertificatesNobodyOwns(data: {
|
|
508
|
+
owners: Array<{
|
|
509
|
+
name: string;
|
|
510
|
+
getOwnedDomains: (domains: Array<string>) => Promise<Array<string>>;
|
|
511
|
+
}>;
|
|
512
|
+
}): Promise<number> {
|
|
513
|
+
const expiredBefore: Date = OneUptimeDate.addRemoveDays(
|
|
514
|
+
OneUptimeDate.getCurrentDate(),
|
|
515
|
+
-GreenlockUtil.REMOVE_UNOWNED_AFTER_EXPIRY_IN_DAYS,
|
|
516
|
+
);
|
|
517
|
+
|
|
518
|
+
const expiredCertificates: Array<AcmeCertificate> =
|
|
519
|
+
await AcmeCertificateService.findAllBy({
|
|
520
|
+
query: {
|
|
521
|
+
expiresAt: QueryHelper.lessThan(expiredBefore),
|
|
522
|
+
},
|
|
523
|
+
select: {
|
|
524
|
+
_id: true,
|
|
525
|
+
domain: true,
|
|
526
|
+
expiresAt: true,
|
|
527
|
+
},
|
|
528
|
+
sort: {
|
|
529
|
+
expiresAt: SortOrder.Ascending,
|
|
530
|
+
},
|
|
531
|
+
skip: 0,
|
|
532
|
+
props: {
|
|
533
|
+
isRoot: true,
|
|
534
|
+
},
|
|
535
|
+
});
|
|
536
|
+
|
|
537
|
+
const candidates: Array<AcmeCertificate> = expiredCertificates.filter(
|
|
538
|
+
(certificate: AcmeCertificate) => {
|
|
539
|
+
return Boolean(certificate.domain) && Boolean(certificate.id);
|
|
540
|
+
},
|
|
541
|
+
);
|
|
542
|
+
|
|
543
|
+
if (candidates.length === 0) {
|
|
544
|
+
return 0;
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
const domains: Array<string> = candidates.map(
|
|
548
|
+
(certificate: AcmeCertificate) => {
|
|
549
|
+
return certificate.domain as string;
|
|
550
|
+
},
|
|
551
|
+
);
|
|
552
|
+
|
|
553
|
+
const ownedDomains: Set<string> = new Set<string>();
|
|
554
|
+
|
|
555
|
+
for (const owner of data.owners) {
|
|
556
|
+
const ownedByThisOwner: Set<string> = await GreenlockUtil.getOwnedAmong({
|
|
557
|
+
domains: domains,
|
|
558
|
+
getOwnedDomains: owner.getOwnedDomains,
|
|
559
|
+
});
|
|
560
|
+
|
|
561
|
+
for (const domain of ownedByThisOwner) {
|
|
562
|
+
ownedDomains.add(domain);
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
const abandoned: Array<AcmeCertificate> = candidates
|
|
567
|
+
.filter((certificate: AcmeCertificate) => {
|
|
568
|
+
return !ownedDomains.has(certificate.domain as string);
|
|
569
|
+
})
|
|
570
|
+
.slice(0, GreenlockUtil.REMOVE_UNOWNED_MAX_PER_RUN);
|
|
571
|
+
|
|
572
|
+
let removedCount: number = 0;
|
|
573
|
+
|
|
574
|
+
for (const certificate of abandoned) {
|
|
575
|
+
logger.debug(
|
|
576
|
+
`Deleting the certificate of ${certificate.domain}: it expired on ${certificate.expiresAt?.toISOString()} and no status page, dashboard or primary host claims it.`,
|
|
577
|
+
{ domain: certificate.domain } as LogAttributes,
|
|
578
|
+
);
|
|
579
|
+
|
|
580
|
+
const deletedCount: number = await AcmeCertificateService.hardDeleteBy({
|
|
581
|
+
query: {
|
|
582
|
+
_id: certificate.id!.toString(),
|
|
583
|
+
domain: certificate.domain as string,
|
|
584
|
+
expiresAt: QueryHelper.lessThan(expiredBefore),
|
|
585
|
+
},
|
|
586
|
+
limit: 1,
|
|
587
|
+
skip: 0,
|
|
588
|
+
props: {
|
|
589
|
+
isRoot: true,
|
|
590
|
+
},
|
|
591
|
+
});
|
|
592
|
+
|
|
593
|
+
removedCount += deletedCount;
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
return removedCount;
|
|
597
|
+
}
|
|
598
|
+
|
|
167
599
|
/*
|
|
168
600
|
* Renew one domain. Never throws: one domain that cannot be renewed - a CNAME
|
|
169
601
|
* that no longer points here, a challenge the CA would not accept - must not
|
|
170
602
|
* take down the rest of the run with it.
|
|
603
|
+
*
|
|
604
|
+
* The renewal runs with the name's order lock held, so it never overlaps a
|
|
605
|
+
* reissue, a Check now or a re-order of the same name, and it looks the
|
|
606
|
+
* certificate up again under that lock: one of those may have replaced it
|
|
607
|
+
* since this run read the table, and renewing it again would spend an
|
|
608
|
+
* order on a duplicate.
|
|
609
|
+
*
|
|
610
|
+
* A CNAME check that fails never deletes a certificate that is still
|
|
611
|
+
* valid. It used to, and a moment's DNS trouble during a renewal took a
|
|
612
|
+
* domain off HTTPS with weeks left on its certificate. Now the renewal is
|
|
613
|
+
* skipped while the certificate keeps serving, and the failure is
|
|
614
|
+
* recorded (CertificateOrderFailures): the domain's Status column says so,
|
|
615
|
+
* and the name waits before the next attempt, longer after each failure
|
|
616
|
+
* in a row - without that, a domain whose record really is gone would take
|
|
617
|
+
* a slot of every run until its certificate expired, and keep the
|
|
618
|
+
* renewals behind it waiting. Only a certificate that has already expired
|
|
619
|
+
* - it serves nobody - is removed when the check fails, so the domain is
|
|
620
|
+
* ordered afresh once its record is back.
|
|
171
621
|
*/
|
|
172
622
|
private static async renewCertForDomain(data: {
|
|
173
623
|
domain: string;
|
|
@@ -185,43 +635,98 @@ export default class GreenlockUtil {
|
|
|
185
635
|
certLogAttributes,
|
|
186
636
|
);
|
|
187
637
|
|
|
638
|
+
const lock: CertificateOrderLockHandle | null =
|
|
639
|
+
await CertificateOrderLock.tryLock(domain);
|
|
640
|
+
|
|
641
|
+
if (!lock) {
|
|
642
|
+
logger.debug(
|
|
643
|
+
`Not renewing the certificate of ${domain} now: another order for it is running. A later run renews it if it is still due.`,
|
|
644
|
+
certLogAttributes,
|
|
645
|
+
);
|
|
646
|
+
return;
|
|
647
|
+
}
|
|
648
|
+
|
|
188
649
|
try {
|
|
189
|
-
|
|
190
|
-
const isValidCname: boolean = await data.validateCname(domain);
|
|
650
|
+
const now: Date = OneUptimeDate.getCurrentDate();
|
|
191
651
|
|
|
192
|
-
|
|
652
|
+
const certificate: AcmeCertificate | undefined = (
|
|
653
|
+
await GreenlockUtil.findCertificatesByDomain([lock.domain])
|
|
654
|
+
).get(lock.domain);
|
|
655
|
+
|
|
656
|
+
if (!certificate) {
|
|
193
657
|
logger.debug(
|
|
194
|
-
`
|
|
658
|
+
`Not renewing the certificate of ${domain}: it is gone. The domain's owner re-orders a missing certificate.`,
|
|
195
659
|
certLogAttributes,
|
|
196
660
|
);
|
|
661
|
+
return;
|
|
662
|
+
}
|
|
197
663
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
logger.error(
|
|
203
|
-
`Cname is not valid for domain: ${domain}`,
|
|
664
|
+
if (!GreenlockUtil.isDueForRenewal(certificate, now)) {
|
|
665
|
+
logger.debug(
|
|
666
|
+
`Not renewing the certificate of ${domain}: another order has renewed it since this run started.`,
|
|
204
667
|
certLogAttributes,
|
|
205
668
|
);
|
|
206
|
-
|
|
207
|
-
|
|
669
|
+
return;
|
|
670
|
+
}
|
|
208
671
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
672
|
+
const isValidCname: boolean = await data.validateCname(domain);
|
|
673
|
+
|
|
674
|
+
if (!isValidCname) {
|
|
675
|
+
const hasExpired: boolean = !OneUptimeDate.isAfter(
|
|
676
|
+
certificate.expiresAt as Date,
|
|
677
|
+
now,
|
|
678
|
+
);
|
|
679
|
+
|
|
680
|
+
if (!hasExpired) {
|
|
681
|
+
logger.debug(
|
|
682
|
+
`CNAME of ${domain} did not validate: keeping its certificate, valid until ${certificate.expiresAt?.toISOString()}, and renewing it on a later run.`,
|
|
683
|
+
certLogAttributes,
|
|
684
|
+
);
|
|
685
|
+
|
|
686
|
+
await CertificateOrderFailures.record({
|
|
687
|
+
domain: domain,
|
|
688
|
+
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.`,
|
|
689
|
+
now: now,
|
|
690
|
+
});
|
|
691
|
+
|
|
692
|
+
return;
|
|
693
|
+
}
|
|
213
694
|
|
|
214
695
|
logger.debug(
|
|
215
|
-
`
|
|
696
|
+
`CNAME of ${domain} did not validate and its certificate has expired: removing the certificate.`,
|
|
216
697
|
certLogAttributes,
|
|
217
698
|
);
|
|
699
|
+
|
|
700
|
+
await GreenlockUtil.removeDomain(domain);
|
|
701
|
+
await data.notifyDomainRemoved(domain);
|
|
702
|
+
|
|
703
|
+
return;
|
|
218
704
|
}
|
|
705
|
+
|
|
706
|
+
logger.debug(`CNAME is valid for domain: ${domain}`, certLogAttributes);
|
|
707
|
+
|
|
708
|
+
const outcome: CertificateOrderOutcome = await GreenlockUtil.orderCert({
|
|
709
|
+
domain: domain,
|
|
710
|
+
reason: CertificateOrderReason.Renewal,
|
|
711
|
+
// Checked a moment ago, above.
|
|
712
|
+
validateCname: null,
|
|
713
|
+
lock: lock,
|
|
714
|
+
});
|
|
715
|
+
|
|
716
|
+
logger.debug(
|
|
717
|
+
outcome === CertificateOrderOutcome.Ordered
|
|
718
|
+
? `Certificate renewed for domain: ${domain}`
|
|
719
|
+
: `Certificate of ${domain} not renewed now (${outcome}): a later run renews it.`,
|
|
720
|
+
certLogAttributes,
|
|
721
|
+
);
|
|
219
722
|
} catch (e) {
|
|
220
723
|
logger.error(
|
|
221
724
|
`Error renewing certificate for domain: ${domain}`,
|
|
222
725
|
certLogAttributes,
|
|
223
726
|
);
|
|
224
727
|
logger.error(e, certLogAttributes);
|
|
728
|
+
} finally {
|
|
729
|
+
await CertificateOrderLock.release(lock);
|
|
225
730
|
}
|
|
226
731
|
}
|
|
227
732
|
|
|
@@ -245,43 +750,111 @@ export default class GreenlockUtil {
|
|
|
245
750
|
}
|
|
246
751
|
}
|
|
247
752
|
|
|
753
|
+
/*
|
|
754
|
+
* Order a certificate for a name from Let's Encrypt and store it. Every
|
|
755
|
+
* certificate this installation orders is ordered here, whoever asks -
|
|
756
|
+
* Check now, the sweeps, the order and reissue APIs, the renewal runs and
|
|
757
|
+
* CoreSSL - so what must hold for every order holds here:
|
|
758
|
+
*
|
|
759
|
+
* - One order per name at a time. The order runs under the name's lock
|
|
760
|
+
* (CertificateOrderLock): the one the caller hands in, or one taken
|
|
761
|
+
* here. A name whose lock is taken is not ordered (NotOrderedNow).
|
|
762
|
+
* - The installation's Let's Encrypt allowance. Each order takes one unit
|
|
763
|
+
* of CertificateOrderBudget for its reason, and none is placed when
|
|
764
|
+
* there is none left (LimitReached).
|
|
765
|
+
* - Nothing is deleted. A CNAME check that fails refuses the order and
|
|
766
|
+
* leaves the name's certificate as it is. It used to remove it, so a
|
|
767
|
+
* DNS blip during a reissue, a renewal or a dashboard order took a
|
|
768
|
+
* working domain off HTTPS.
|
|
769
|
+
* - A failed order is recorded (CertificateOrderFailures) for the
|
|
770
|
+
* domain's Status column and the retry delay of the sweeps, and a
|
|
771
|
+
* successful one clears that record.
|
|
772
|
+
*
|
|
773
|
+
* Throws when the CNAME check fails or the order fails, with a message the
|
|
774
|
+
* caller can show.
|
|
775
|
+
*/
|
|
248
776
|
@CaptureSpan()
|
|
249
777
|
public static async orderCert(data: {
|
|
250
778
|
domain: string;
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
779
|
+
reason: CertificateOrderReason;
|
|
780
|
+
/*
|
|
781
|
+
* Checks, before anything is spent, that the domain still points here:
|
|
782
|
+
* an order for a name whose record is gone only fails, and counts as a
|
|
783
|
+
* failed validation. Null when the caller has just checked it - a second
|
|
784
|
+
* check only gives a DNS blip one more chance to refuse an order the
|
|
785
|
+
* first check allowed.
|
|
786
|
+
*/
|
|
787
|
+
validateCname: ((domain: string) => Promise<boolean>) | null;
|
|
788
|
+
// The name's order lock, when the caller holds it already.
|
|
789
|
+
lock?: CertificateOrderLockHandle | undefined;
|
|
790
|
+
/*
|
|
791
|
+
* The caller's own share of orders - a sweep's budget, the on-demand
|
|
792
|
+
* one - asked once the CNAME check has passed and before the
|
|
793
|
+
* installation's budget, so a share is not spent on a domain whose
|
|
794
|
+
* record is gone. False orders nothing (LimitReached).
|
|
795
|
+
*/
|
|
796
|
+
mayOrder?: (() => Promise<boolean>) | undefined;
|
|
797
|
+
}): Promise<CertificateOrderOutcome> {
|
|
798
|
+
const domain: string = CertificateOrderLock.normalizeDomain(data.domain);
|
|
256
799
|
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
800
|
+
if (data.lock && !CertificateOrderLock.isHeldFor(data.lock, domain)) {
|
|
801
|
+
/*
|
|
802
|
+
* Redis lost the lock while the caller held it: another order of the
|
|
803
|
+
* name may be running now. Not the caller's mistake - just not now.
|
|
804
|
+
*/
|
|
805
|
+
if (CertificateOrderLock.wasLost(data.lock, domain)) {
|
|
806
|
+
logger.debug(
|
|
807
|
+
`Not ordering a certificate for ${domain}: the lock on the name was lost before the order`,
|
|
808
|
+
{ domain: domain } as LogAttributes,
|
|
809
|
+
);
|
|
262
810
|
|
|
263
|
-
|
|
811
|
+
return CertificateOrderOutcome.NotOrderedNow;
|
|
812
|
+
}
|
|
264
813
|
|
|
265
|
-
|
|
266
|
-
|
|
814
|
+
throw new BadDataException(
|
|
815
|
+
`The certificate order lock handed in for ${domain} is not held.`,
|
|
816
|
+
);
|
|
817
|
+
}
|
|
267
818
|
|
|
268
|
-
|
|
819
|
+
const lock: CertificateOrderLockHandle | null =
|
|
820
|
+
data.lock || (await CertificateOrderLock.tryLock(domain));
|
|
269
821
|
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
822
|
+
if (!lock) {
|
|
823
|
+
return CertificateOrderOutcome.NotOrderedNow;
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
try {
|
|
827
|
+
return await GreenlockUtil.orderCertWithLockHeld({
|
|
828
|
+
domain: domain,
|
|
829
|
+
reason: data.reason,
|
|
830
|
+
validateCname: data.validateCname,
|
|
831
|
+
mayOrder: data.mayOrder,
|
|
832
|
+
});
|
|
833
|
+
} finally {
|
|
834
|
+
if (!data.lock) {
|
|
835
|
+
await CertificateOrderLock.release(lock);
|
|
274
836
|
}
|
|
837
|
+
}
|
|
838
|
+
}
|
|
275
839
|
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
840
|
+
private static async orderCertWithLockHeld(data: {
|
|
841
|
+
domain: string;
|
|
842
|
+
reason: CertificateOrderReason;
|
|
843
|
+
validateCname: ((domain: string) => Promise<boolean>) | null;
|
|
844
|
+
mayOrder?: (() => Promise<boolean>) | undefined;
|
|
845
|
+
}): Promise<CertificateOrderOutcome> {
|
|
846
|
+
const { domain } = data;
|
|
280
847
|
|
|
281
|
-
|
|
848
|
+
const orderLogAttributes: LogAttributes = {
|
|
849
|
+
domain: domain,
|
|
850
|
+
};
|
|
282
851
|
|
|
283
|
-
|
|
852
|
+
logger.debug(
|
|
853
|
+
`GreenlockUtil - Ordering certificate for domain: ${domain} (${data.reason})`,
|
|
854
|
+
orderLogAttributes,
|
|
855
|
+
);
|
|
284
856
|
|
|
857
|
+
if (data.validateCname) {
|
|
285
858
|
logger.debug(
|
|
286
859
|
`Validating cname for domain: ${domain}`,
|
|
287
860
|
orderLogAttributes,
|
|
@@ -290,139 +863,221 @@ export default class GreenlockUtil {
|
|
|
290
863
|
const isValidCname: boolean = await data.validateCname(domain);
|
|
291
864
|
|
|
292
865
|
if (!isValidCname) {
|
|
293
|
-
logger.debug(
|
|
294
|
-
`CNAME is not valid for domain: ${domain}`,
|
|
295
|
-
orderLogAttributes,
|
|
296
|
-
);
|
|
297
|
-
logger.debug(`Removing domain: ${domain}`, orderLogAttributes);
|
|
298
|
-
|
|
299
|
-
await GreenlockUtil.removeDomain(domain);
|
|
300
866
|
logger.error(
|
|
301
|
-
`Cname is not valid for domain: ${domain}
|
|
867
|
+
`Cname is not valid for domain: ${domain}. Not ordering, and keeping its certificate, if it has one.`,
|
|
302
868
|
orderLogAttributes,
|
|
303
869
|
);
|
|
870
|
+
|
|
304
871
|
throw new BadDataException("Cname is not valid for domain " + domain);
|
|
305
872
|
}
|
|
306
873
|
|
|
307
874
|
logger.debug(`Cname is valid for domain: ${domain}`, orderLogAttributes);
|
|
875
|
+
}
|
|
308
876
|
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
877
|
+
if (data.mayOrder && !(await data.mayOrder())) {
|
|
878
|
+
logger.debug(
|
|
879
|
+
`Not ordering a certificate for ${domain} now: this window's orders of its kind are used up`,
|
|
880
|
+
orderLogAttributes,
|
|
881
|
+
);
|
|
882
|
+
|
|
883
|
+
return CertificateOrderOutcome.LimitReached;
|
|
884
|
+
}
|
|
885
|
+
|
|
886
|
+
try {
|
|
887
|
+
const acmeAccountKeyInBase64: string = LetsEncryptAccountKey;
|
|
888
|
+
|
|
889
|
+
if (!acmeAccountKeyInBase64) {
|
|
890
|
+
throw new ServerException(
|
|
891
|
+
"No lets encrypt account key found in environment variables. Please add one.",
|
|
892
|
+
);
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
if (
|
|
896
|
+
!(await CertificateOrderBudget.takeSlot({
|
|
897
|
+
reason: data.reason,
|
|
898
|
+
now: OneUptimeDate.getCurrentDate(),
|
|
899
|
+
domain: domain,
|
|
900
|
+
}))
|
|
901
|
+
) {
|
|
902
|
+
return CertificateOrderOutcome.LimitReached;
|
|
903
|
+
}
|
|
904
|
+
|
|
905
|
+
await GreenlockUtil.orderAndStoreCertificate({
|
|
906
|
+
domain: domain,
|
|
907
|
+
acmeAccountKeyInBase64: acmeAccountKeyInBase64,
|
|
908
|
+
orderLogAttributes: orderLogAttributes,
|
|
312
909
|
});
|
|
910
|
+
} catch (e) {
|
|
911
|
+
logger.error(
|
|
912
|
+
`Error ordering certificate for domain: ${domain}`,
|
|
913
|
+
orderLogAttributes,
|
|
914
|
+
);
|
|
915
|
+
logger.error(e, orderLogAttributes);
|
|
916
|
+
|
|
917
|
+
const error: Exception = GreenlockUtil.toOrderError(e, domain);
|
|
313
918
|
|
|
314
|
-
|
|
315
|
-
|
|
919
|
+
await CertificateOrderFailures.record({
|
|
920
|
+
domain: domain,
|
|
921
|
+
error: error.message,
|
|
922
|
+
now: OneUptimeDate.getCurrentDate(),
|
|
316
923
|
});
|
|
317
924
|
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
925
|
+
throw error;
|
|
926
|
+
}
|
|
927
|
+
|
|
928
|
+
await CertificateOrderFailures.clear(domain);
|
|
929
|
+
|
|
930
|
+
return CertificateOrderOutcome.Ordered;
|
|
931
|
+
}
|
|
932
|
+
|
|
933
|
+
// What the caller of a failed order is told.
|
|
934
|
+
private static toOrderError(e: unknown, domain: string): Exception {
|
|
935
|
+
if (e instanceof Exception) {
|
|
936
|
+
return e;
|
|
937
|
+
}
|
|
938
|
+
|
|
939
|
+
if (IsBillingEnabled) {
|
|
940
|
+
return new ServerException(
|
|
941
|
+
`Unable to order certificate for ${domain}. Please contact support at support@oneuptime.com for more information.`,
|
|
321
942
|
);
|
|
943
|
+
}
|
|
322
944
|
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
const acmeChallenge: AcmeChallenge = new AcmeChallenge();
|
|
342
|
-
acmeChallenge.challenge = keyAuthorization;
|
|
343
|
-
acmeChallenge.token = challenge.token;
|
|
344
|
-
acmeChallenge.domain = authz.identifier.value;
|
|
345
|
-
|
|
346
|
-
await AcmeChallengeService.create({
|
|
347
|
-
data: acmeChallenge,
|
|
348
|
-
props: {
|
|
349
|
-
isRoot: true,
|
|
350
|
-
},
|
|
351
|
-
});
|
|
352
|
-
|
|
353
|
-
logger.debug(
|
|
354
|
-
`Challenge created for domain: ${authz.identifier.value}`,
|
|
355
|
-
orderLogAttributes,
|
|
356
|
-
);
|
|
357
|
-
}
|
|
358
|
-
},
|
|
359
|
-
challengeRemoveFn: async (
|
|
360
|
-
authz: acme.Authorization,
|
|
361
|
-
challenge: Challenge,
|
|
362
|
-
) => {
|
|
363
|
-
// Clean up challenge here
|
|
945
|
+
return new ServerException(
|
|
946
|
+
`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.`,
|
|
947
|
+
);
|
|
948
|
+
}
|
|
949
|
+
|
|
950
|
+
private static async orderAndStoreCertificate(data: {
|
|
951
|
+
domain: string;
|
|
952
|
+
acmeAccountKeyInBase64: string;
|
|
953
|
+
orderLogAttributes: LogAttributes;
|
|
954
|
+
}): Promise<void> {
|
|
955
|
+
const { domain, orderLogAttributes } = data;
|
|
956
|
+
|
|
957
|
+
let acmeAccountKey: string = Buffer.from(
|
|
958
|
+
data.acmeAccountKeyInBase64,
|
|
959
|
+
"base64",
|
|
960
|
+
).toString();
|
|
961
|
+
|
|
962
|
+
acmeAccountKey = Text.replaceAll(acmeAccountKey, "\\n", "\n");
|
|
364
963
|
|
|
964
|
+
const client: acme.Client = new acme.Client({
|
|
965
|
+
directoryUrl: acme.directory.letsencrypt.production,
|
|
966
|
+
accountKey: acmeAccountKey,
|
|
967
|
+
});
|
|
968
|
+
|
|
969
|
+
const [certificateKey, certificateRequest] = await acme.crypto.createCsr({
|
|
970
|
+
commonName: domain,
|
|
971
|
+
});
|
|
972
|
+
|
|
973
|
+
logger.debug(
|
|
974
|
+
`Ordering certificate for domain: ${domain}`,
|
|
975
|
+
orderLogAttributes,
|
|
976
|
+
);
|
|
977
|
+
|
|
978
|
+
const certificate: string = await client.auto({
|
|
979
|
+
csr: certificateRequest,
|
|
980
|
+
email: LetsEncryptNotificationEmail.toString(),
|
|
981
|
+
termsOfServiceAgreed: true,
|
|
982
|
+
challengePriority: ["http-01"], // only http-01 challenge is supported by oneuptime
|
|
983
|
+
challengeCreateFn: async (
|
|
984
|
+
authz: acme.Authorization,
|
|
985
|
+
challenge: Challenge,
|
|
986
|
+
keyAuthorization: string,
|
|
987
|
+
) => {
|
|
988
|
+
// Satisfy challenge here
|
|
989
|
+
/* http-01 */
|
|
990
|
+
if (challenge.type === "http-01") {
|
|
365
991
|
logger.debug(
|
|
366
|
-
`
|
|
992
|
+
`Creating challenge for domain: ${authz.identifier.value}`,
|
|
367
993
|
orderLogAttributes,
|
|
368
994
|
);
|
|
369
995
|
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
}
|
|
996
|
+
const acmeChallenge: AcmeChallenge = new AcmeChallenge();
|
|
997
|
+
acmeChallenge.challenge = keyAuthorization;
|
|
998
|
+
acmeChallenge.token = challenge.token;
|
|
999
|
+
acmeChallenge.domain = authz.identifier.value;
|
|
1000
|
+
|
|
1001
|
+
await AcmeChallengeService.create({
|
|
1002
|
+
data: acmeChallenge,
|
|
1003
|
+
props: {
|
|
1004
|
+
isRoot: true,
|
|
1005
|
+
},
|
|
1006
|
+
});
|
|
382
1007
|
|
|
383
1008
|
logger.debug(
|
|
384
|
-
`Challenge
|
|
1009
|
+
`Challenge created for domain: ${authz.identifier.value}`,
|
|
385
1010
|
orderLogAttributes,
|
|
386
1011
|
);
|
|
387
|
-
}
|
|
388
|
-
}
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
1012
|
+
}
|
|
1013
|
+
},
|
|
1014
|
+
challengeRemoveFn: async (
|
|
1015
|
+
authz: acme.Authorization,
|
|
1016
|
+
challenge: Challenge,
|
|
1017
|
+
) => {
|
|
1018
|
+
// Clean up challenge here
|
|
394
1019
|
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
const expiresAt: Date = cert.notAfter;
|
|
400
|
-
|
|
401
|
-
logger.debug(`Certificate expires at: ${expiresAt}`, orderLogAttributes);
|
|
402
|
-
logger.debug(`Certificate issued at: ${issuedAt}`, orderLogAttributes);
|
|
1020
|
+
logger.debug(
|
|
1021
|
+
`Removing challenge for domain: ${authz.identifier.value}`,
|
|
1022
|
+
orderLogAttributes,
|
|
1023
|
+
);
|
|
403
1024
|
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
});
|
|
1025
|
+
if (challenge.type === "http-01") {
|
|
1026
|
+
await AcmeChallengeService.deleteBy({
|
|
1027
|
+
query: {
|
|
1028
|
+
domain: authz.identifier.value,
|
|
1029
|
+
},
|
|
1030
|
+
limit: 1,
|
|
1031
|
+
skip: 0,
|
|
1032
|
+
props: {
|
|
1033
|
+
isRoot: true,
|
|
1034
|
+
},
|
|
1035
|
+
});
|
|
1036
|
+
}
|
|
417
1037
|
|
|
418
|
-
if (existingCertificate) {
|
|
419
1038
|
logger.debug(
|
|
420
|
-
`
|
|
1039
|
+
`Challenge removed for domain: ${authz.identifier.value}`,
|
|
421
1040
|
orderLogAttributes,
|
|
422
1041
|
);
|
|
1042
|
+
},
|
|
1043
|
+
});
|
|
423
1044
|
|
|
424
|
-
|
|
425
|
-
|
|
1045
|
+
logger.debug(
|
|
1046
|
+
`Certificate ordered for domain: ${domain}`,
|
|
1047
|
+
orderLogAttributes,
|
|
1048
|
+
);
|
|
1049
|
+
|
|
1050
|
+
// get expires at date from certificate
|
|
1051
|
+
const cert: acme.CertificateInfo =
|
|
1052
|
+
acme.crypto.readCertificateInfo(certificate);
|
|
1053
|
+
const issuedAt: Date = cert.notBefore;
|
|
1054
|
+
const expiresAt: Date = cert.notAfter;
|
|
1055
|
+
|
|
1056
|
+
logger.debug(`Certificate expires at: ${expiresAt}`, orderLogAttributes);
|
|
1057
|
+
logger.debug(`Certificate issued at: ${issuedAt}`, orderLogAttributes);
|
|
1058
|
+
|
|
1059
|
+
// check if the certificate is already in the database.
|
|
1060
|
+
const existingCertificate: AcmeCertificate | null =
|
|
1061
|
+
await AcmeCertificateService.findOneBy({
|
|
1062
|
+
query: {
|
|
1063
|
+
domain: domain,
|
|
1064
|
+
},
|
|
1065
|
+
select: {
|
|
1066
|
+
_id: true,
|
|
1067
|
+
},
|
|
1068
|
+
props: {
|
|
1069
|
+
isRoot: true,
|
|
1070
|
+
},
|
|
1071
|
+
});
|
|
1072
|
+
|
|
1073
|
+
/*
|
|
1074
|
+
* The row can be removed between the look-up above and this write (a
|
|
1075
|
+
* domain deleted meanwhile, or the cleanup of expired certificates
|
|
1076
|
+
* nobody owned). Then the update finds nothing, and the certificate
|
|
1077
|
+
* the CA has just issued is stored in a new row instead of being lost.
|
|
1078
|
+
*/
|
|
1079
|
+
const updatedCount: number = existingCertificate
|
|
1080
|
+
? await AcmeCertificateService.updateBy({
|
|
426
1081
|
query: {
|
|
427
1082
|
domain: domain,
|
|
428
1083
|
},
|
|
@@ -437,58 +1092,39 @@ export default class GreenlockUtil {
|
|
|
437
1092
|
props: {
|
|
438
1093
|
isRoot: true,
|
|
439
1094
|
},
|
|
440
|
-
})
|
|
1095
|
+
})
|
|
1096
|
+
: 0;
|
|
441
1097
|
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
1098
|
+
if (updatedCount > 0) {
|
|
1099
|
+
logger.debug(
|
|
1100
|
+
`Certificate updated for domain: ${domain}`,
|
|
1101
|
+
orderLogAttributes,
|
|
1102
|
+
);
|
|
1103
|
+
} else {
|
|
1104
|
+
logger.debug(
|
|
1105
|
+
`Creating certificate for domain: ${domain}`,
|
|
1106
|
+
orderLogAttributes,
|
|
1107
|
+
);
|
|
1108
|
+
// create the certificate
|
|
1109
|
+
const acmeCertificate: AcmeCertificate = new AcmeCertificate();
|
|
453
1110
|
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
1111
|
+
acmeCertificate.domain = domain;
|
|
1112
|
+
acmeCertificate.certificate = certificate.toString();
|
|
1113
|
+
acmeCertificate.certificateKey = certificateKey.toString();
|
|
1114
|
+
acmeCertificate.issuedAt = issuedAt;
|
|
1115
|
+
acmeCertificate.expiresAt = expiresAt;
|
|
459
1116
|
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
1117
|
+
await AcmeCertificateService.create({
|
|
1118
|
+
data: acmeCertificate,
|
|
1119
|
+
props: {
|
|
1120
|
+
isRoot: true,
|
|
1121
|
+
},
|
|
1122
|
+
});
|
|
466
1123
|
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
orderLogAttributes,
|
|
470
|
-
);
|
|
471
|
-
}
|
|
472
|
-
} catch (e) {
|
|
473
|
-
logger.error(
|
|
474
|
-
`Error ordering certificate for domain: ${data.domain}`,
|
|
1124
|
+
logger.debug(
|
|
1125
|
+
`Certificate created for domain: ${domain}`,
|
|
475
1126
|
orderLogAttributes,
|
|
476
1127
|
);
|
|
477
|
-
logger.error(e, orderLogAttributes);
|
|
478
|
-
|
|
479
|
-
if (e instanceof Exception) {
|
|
480
|
-
throw e;
|
|
481
|
-
}
|
|
482
|
-
|
|
483
|
-
if (IsBillingEnabled) {
|
|
484
|
-
throw new ServerException(
|
|
485
|
-
`Unable to order certificate for ${data.domain}. Please contact support at support@oneuptime.com for more information.`,
|
|
486
|
-
);
|
|
487
|
-
} else {
|
|
488
|
-
throw new ServerException(
|
|
489
|
-
`Unable to order certificate for ${data.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.`,
|
|
490
|
-
);
|
|
491
|
-
}
|
|
492
1128
|
}
|
|
493
1129
|
}
|
|
494
1130
|
}
|