@oneuptime/common 14.0.6 → 14.0.8
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/Incident.ts +267 -1
- package/Models/DatabaseModels/IncidentCustomField.ts +202 -0
- package/Models/DatabaseModels/IncidentEpisode.ts +30 -0
- package/Models/DatabaseModels/IncidentTemplate.ts +126 -1
- package/Models/DatabaseModels/InventoryItem.ts +23 -12
- package/Models/DatabaseModels/StatusPage.ts +55 -0
- package/Models/DatabaseModels/StatusPageSubscriber.ts +128 -0
- package/Server/API/IncidentAPI.ts +162 -0
- package/Server/API/StatusPageAPI.ts +487 -171
- package/Server/API/StatusPageSubscriberAPI.ts +63 -15
- package/Server/Infrastructure/Postgres/SchemaMigrations/1795200000000-AddInventoryItemProjectEntityKeyIndex.ts +217 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1795300000000-SkipHiddenIncidentCreatedNotifications.ts +49 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1795400000000-AddIncidentStatusPageScope.ts +108 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1795500000000-AddIncidentTemplateStatusPageScopeFlag.ts +33 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1795600000000-AddStatusPageSubscriberUnsubscribeToken.ts +51 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1795700000000-AddStatusPageSubscriberIsAddedByTeam.ts +33 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1795800000000-AddIncidentCustomFieldCreateAndNotificationSettings.ts +168 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1795900000000-AddSubscriberNotificationClaimedAt.ts +44 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +16 -0
- package/Server/Infrastructure/Semaphore.ts +10 -0
- package/Server/Middleware/IdentityRateLimit.ts +108 -3
- package/Server/Middleware/SubscriberNotificationPreviewRateLimit.ts +237 -0
- package/Server/Middleware/SubscriberNotificationTestSendRateLimit.ts +304 -0
- package/Server/Services/AlertService.ts +32 -36
- package/Server/Services/DatabaseService.ts +93 -10
- package/Server/Services/IncidentAlertService.ts +609 -2
- package/Server/Services/IncidentCustomFieldService.ts +276 -1
- package/Server/Services/IncidentEpisodePublicNoteService.ts +28 -0
- package/Server/Services/IncidentEpisodeService.ts +15 -0
- package/Server/Services/IncidentEpisodeStateTimelineService.ts +27 -1
- package/Server/Services/IncidentPublicNoteService.ts +30 -1
- package/Server/Services/IncidentService.ts +1663 -103
- package/Server/Services/IncidentStateTimelineService.ts +13 -0
- package/Server/Services/IncidentTemplateService.ts +109 -0
- package/Server/Services/InventoryItemService.ts +38 -0
- package/Server/Services/IoTDeviceCredentialService.ts +13 -4
- package/Server/Services/ScheduledMaintenancePublicNoteService.ts +30 -1
- package/Server/Services/ScheduledMaintenanceService.ts +118 -64
- package/Server/Services/SmsService.ts +10 -0
- package/Server/Services/StatusPageService.ts +65 -8
- package/Server/Services/StatusPageSubscriberNotificationTemplateService.ts +299 -37
- package/Server/Services/StatusPageSubscriberNotificationTemplateStatusPageService.ts +129 -0
- package/Server/Services/StatusPageSubscriberService.ts +1161 -64
- package/Server/Services/UserNotificationRuleService.ts +55 -53
- package/Server/Services/WorkspaceNotificationSummaryService.ts +38 -20
- package/Server/Types/Markdown.ts +153 -6
- package/Server/Types/Workflow/Components/Email.ts +61 -2
- package/Server/Utils/AffectedResources/LinkedAffectedResources.ts +576 -0
- package/Server/Utils/Alert/AlertStateChangeAuthorization.ts +129 -0
- package/Server/Utils/CustomField/CustomFieldRename.ts +378 -0
- package/Server/Utils/DataSource/EgressGuard.ts +66 -21
- package/Server/Utils/Inventory/InventoryOverviewAggregation.ts +111 -0
- package/Server/Utils/Mail/PinnedSmtpSocket.ts +130 -0
- package/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.ts +10 -0
- package/Server/Utils/Response.ts +31 -0
- package/Server/Utils/SSRFProtection.ts +76 -16
- package/Server/Utils/StatusPage/IncidentStatusPageScope.ts +948 -0
- package/Server/Utils/StatusPage/IncidentSubscriberAudienceBuilder.ts +656 -0
- package/Server/Utils/StatusPage/IncidentTemplateVariableBuilder.ts +805 -0
- package/Server/Utils/StatusPage/StatusPageExclusion.ts +18 -0
- package/Server/Utils/StatusPage/StatusPageReadAccess.ts +125 -0
- package/Server/Utils/StatusPage/StatusPageSubscriberUnsubscribeNotice.ts +151 -0
- package/Server/Utils/StatusPage/StatusPageSubscriberUnsubscribeToken.ts +70 -0
- package/Server/Utils/StatusPage/SubscriberIncidentEmailBuilder.ts +421 -0
- package/Server/Utils/StatusPage/SubscriberNotificationClaim.ts +107 -0
- package/Server/Utils/StatusPage/SubscriberNotificationDeliveryRecord.ts +1049 -0
- package/Server/Utils/StatusPage/SubscriberNotificationFanOut.ts +180 -0
- package/Server/Utils/StatusPage/SubscriberNotificationPreviewBuilder.ts +839 -0
- package/Server/Utils/StatusPage/SubscriberNotificationResendAccess.ts +393 -0
- package/Server/Utils/StatusPage/SubscriberNotificationRunLimit.ts +246 -0
- package/Server/Utils/StatusPage/SubscriberNotificationTiming.ts +133 -0
- package/Server/Utils/StatusPage/SubscriberTemplateIncidentRecordAccess.ts +215 -0
- package/Server/Utils/StatusPageResource.ts +51 -20
- package/Server/Utils/Topology/TopologyConcurrencyLimiter.ts +229 -0
- package/Server/Utils/Topology/TopologyQueries.ts +1350 -0
- package/Server/Utils/Topology/TopologyRequest.ts +463 -0
- package/Server/Utils/Topology/TopologyResponseCache.ts +183 -0
- package/Server/Utils/Topology/TopologySql.ts +1024 -0
- package/Server/Utils/VM/VMAPI.ts +1 -0
- package/Server/Utils/VM/VMRunner.ts +10 -0
- package/Server/Utils/Workflow/OAuth2TokenClient.ts +10 -0
- package/Server/Views/Partials/SensitiveUrlToken.ejs +8 -5
- package/Tests/App/Accounts/RegisterVerifyEmail.test.tsx +748 -0
- package/Tests/App/Accounts/ResendVerificationEmail.test.tsx +1222 -0
- package/Tests/App/Accounts/VerificationEmailResendUtils.test.ts +797 -0
- package/Tests/App/Accounts/VerifyEmailPending.test.tsx +538 -0
- package/Tests/App/Accounts/VerifyEmailResend.test.tsx +779 -0
- package/Tests/App/Dashboard/AcknowledgeAlertsOnDeclare.test.ts +369 -0
- package/Tests/App/Dashboard/AffectedResourcesSlo.test.tsx +1 -1
- package/Tests/App/Dashboard/AffectedResourcesSummaryStep.test.tsx +510 -123
- package/Tests/App/Dashboard/AlertsTableAffectedResources.test.tsx +490 -0
- package/Tests/App/Dashboard/ChangeAlertStateDeclareIncident.test.tsx +886 -0
- package/Tests/App/Dashboard/CreateReviewStepRoleSummary.test.tsx +1250 -0
- package/Tests/App/Dashboard/CreateReviewStepSelectionSummary.test.tsx +738 -0
- package/Tests/App/Dashboard/CustomFieldsSettingsIncidentOptions.test.tsx +357 -0
- package/Tests/App/Dashboard/DeclareIncidentFromAlert.test.ts +417 -0
- package/Tests/App/Dashboard/EntityDetailPanel.test.tsx +1948 -229
- package/Tests/App/Dashboard/EntityDetailPanelLifecycle.test.tsx +493 -0
- package/Tests/App/Dashboard/EntityDetailPanelNavigation.test.tsx +439 -0
- package/Tests/App/Dashboard/EventNotes.test.tsx +776 -0
- package/Tests/App/Dashboard/EventNotesPages.test.tsx +119 -0
- package/Tests/App/Dashboard/EventNotesUtil.test.ts +116 -17
- package/Tests/App/Dashboard/EventOverviewPages.test.tsx +534 -6
- package/Tests/App/Dashboard/EventStatusPanel.test.tsx +798 -2
- package/Tests/App/Dashboard/FetchStateAndSeverityElements.test.tsx +669 -0
- package/Tests/App/Dashboard/FetchUsers.test.tsx +230 -0
- package/Tests/App/Dashboard/IncidentChangeStateNotifyDefault.test.tsx +91 -1
- package/Tests/App/Dashboard/IncidentCreateAcknowledgeAlerts.test.tsx +1611 -0
- package/Tests/App/Dashboard/IncidentCreateDetailsStep.test.tsx +643 -0
- package/Tests/App/Dashboard/IncidentCreateFromAlerts.test.tsx +8 -1
- package/Tests/App/Dashboard/IncidentCreateStatusPageScope.test.tsx +601 -0
- package/Tests/App/Dashboard/IncidentCustomFieldTemplateVariables.test.tsx +386 -0
- package/Tests/App/Dashboard/IncidentNoteTemplatePlaceholders.test.tsx +124 -0
- package/Tests/App/Dashboard/IncidentNoteTemplateVariablesLoader.test.ts +305 -0
- package/Tests/App/Dashboard/IncidentOverviewNotifyDefault.test.tsx +112 -0
- package/Tests/App/Dashboard/IncidentSettingsRenotifyOnPublish.test.tsx +674 -0
- package/Tests/App/Dashboard/IncidentSettingsStatusPageScope.test.tsx +1051 -0
- package/Tests/App/Dashboard/IncidentTemplateCustomFields.test.tsx +384 -0
- package/Tests/App/Dashboard/IncidentTemplateStatusPageScopeCard.test.tsx +215 -0
- package/Tests/App/Dashboard/InfrastructureExplorer.test.tsx +1365 -57
- package/Tests/App/Dashboard/InfrastructureGraph.test.tsx +964 -23
- package/Tests/App/Dashboard/InventoryRelationships.test.tsx +885 -0
- package/Tests/App/Dashboard/PublicNotePagesNotifyDefault.test.tsx +113 -1
- package/Tests/App/Dashboard/ServiceMapDatabaseLink.test.tsx +201 -15
- package/Tests/App/Dashboard/ServiceMapGraph.test.tsx +508 -36
- package/Tests/App/Dashboard/SubscriberAudienceSummary.test.tsx +512 -0
- package/Tests/App/Dashboard/SubscriberNotificationPreviewModal.test.tsx +837 -0
- package/Tests/App/Dashboard/SubscriberNotificationStatusLabel.test.tsx +88 -0
- package/Tests/App/Dashboard/SubscriberNotificationStatusResend.test.tsx +473 -0
- package/Tests/App/Dashboard/SubscriberTemplateLivePreview.test.tsx +196 -0
- package/Tests/App/Dashboard/TeamAddedSubscribersUnsubscribedNotice.test.tsx +248 -0
- package/Tests/App/Dashboard/TopologyDataLifecycle.test.tsx +583 -0
- package/Tests/App/Dashboard/TopologyDataLoading.test.tsx +982 -218
- package/Tests/App/Dashboard/TopologyPageNavigation.test.tsx +818 -114
- package/Tests/App/SensitiveUrlTokenBootstrap.test.ts +64 -3
- package/Tests/App/StatusPage/StatusPageUnsubscribePage.test.tsx +412 -0
- package/Tests/Models/IncidentCustomFieldApiSchemaContract.test.ts +217 -0
- package/Tests/Models/IncidentCustomFieldCreateSettingsColumns.test.ts +252 -0
- package/Tests/Models/StatusPageSubscriberUnsubscribeColumns.test.ts +218 -0
- package/Tests/Server/API/ExpiredSessionRouteGuards.test.ts +7 -0
- package/Tests/Server/API/IncidentSubscriberAudienceAPI.test.ts +1408 -0
- package/Tests/Server/API/StatusPageIncidentScope.test.ts +1868 -0
- package/Tests/Server/API/StatusPageIncidentScopePostgres.test.ts +790 -0
- package/Tests/Server/API/StatusPageManageSubscriptionRecipient.test.ts +10 -1
- package/Tests/Server/API/StatusPageManageSubscriptionTemplateVariables.test.ts +206 -18
- package/Tests/Server/API/StatusPagePostmortemVisibility.test.ts +14 -2
- package/Tests/Server/API/StatusPageSubscriberCreateResponse.test.ts +217 -0
- package/Tests/Server/API/StatusPageSubscriberOwnership.test.ts +103 -2
- package/Tests/Server/API/StatusPageUnsubscribeAPI.test.ts +396 -0
- package/Tests/Server/Infrastructure/Postgres/AddIncidentStatusPageScopeMigration.test.ts +395 -0
- package/Tests/Server/Infrastructure/Postgres/AddIncidentTemplateStatusPageScopeFlagMigration.test.ts +150 -0
- package/Tests/Server/Infrastructure/Postgres/AddSubscriberNotificationClaimedAtMigration.test.ts +156 -0
- package/Tests/Server/Infrastructure/Postgres/RenameInventoryItemMigration.test.ts +90 -21
- package/Tests/Server/Infrastructure/Postgres/SkipHiddenIncidentCreatedNotificationsMigration.test.ts +410 -0
- package/Tests/Server/Middleware/IdentityRateLimit.test.ts +551 -1
- package/Tests/Server/Middleware/SubscriberNotificationPreviewRateLimit.test.ts +238 -0
- package/Tests/Server/Middleware/SubscriberNotificationTestSendRateLimit.test.ts +245 -0
- package/Tests/Server/Services/AddStatusPageSubscriberUnsubscribeTokenMigration.test.ts +152 -0
- package/Tests/Server/Services/CrossProjectRelationWriteGuard.test.ts +221 -36
- package/Tests/Server/Services/DatabaseServiceCompareAndSetColumns.test.ts +191 -0
- package/Tests/Server/Services/DomainService.test.ts +525 -0
- package/Tests/Server/Services/IncidentAlertAcknowledgeOnDeclare.test.ts +2630 -0
- package/Tests/Server/Services/IncidentAlertPostgres.test.ts +1625 -1
- package/Tests/Server/Services/IncidentCreatedRenotifyOnPublish.test.ts +681 -0
- package/Tests/Server/Services/IncidentCreatedResend.test.ts +775 -0
- package/Tests/Server/Services/IncidentCustomFieldRenamePostgres.test.ts +713 -0
- package/Tests/Server/Services/IncidentCustomFieldService.test.ts +751 -0
- package/Tests/Server/Services/IncidentCustomFieldValueValidation.test.ts +556 -0
- package/Tests/Server/Services/IncidentDeclareAcknowledgeAlerts.test.ts +2189 -0
- package/Tests/Server/Services/IncidentStatusPageScope.test.ts +2971 -0
- package/Tests/Server/Services/IncidentStatusPageScopeFeed.test.ts +131 -0
- package/Tests/Server/Services/IncidentStatusPageScopePostgres.test.ts +625 -0
- package/Tests/Server/Services/IncidentTemplateCustomFieldsCopy.test.ts +311 -0
- package/Tests/Server/Services/IncidentTemplateStatusPageScope.test.ts +363 -0
- package/Tests/Server/Services/InventoryItemServiceOverviewCounts.test.ts +345 -0
- package/Tests/Server/Services/InventoryOverviewPostgres.test.ts +254 -0
- package/Tests/Server/Services/IoTDeviceCredentialService.test.ts +819 -0
- package/Tests/Server/Services/LinkedAffectedResourcesCreatedFeed.test.ts +420 -0
- package/Tests/Server/Services/PublicNoteEditFeedEventType.test.ts +213 -0
- package/Tests/Server/Services/PublicNoteResendAccess.test.ts +994 -0
- package/Tests/Server/Services/ScheduledMaintenanceSubscriberTemplateFormats.test.ts +289 -9
- package/Tests/Server/Services/SloAffectedResourceCreatedFeed.test.ts +92 -36
- package/Tests/Server/Services/SmsServiceFailIfNotSent.test.ts +67 -0
- package/Tests/Server/Services/StatusPageReportIncidentCounts.test.ts +610 -0
- package/Tests/Server/Services/StatusPageSubscriberAudienceCounts.test.ts +201 -0
- package/Tests/Server/Services/StatusPageSubscriberAudienceCountsPostgres.test.ts +271 -0
- package/Tests/Server/Services/StatusPageSubscriberConfirmationTemplateEscaping.test.ts +200 -0
- package/Tests/Server/Services/StatusPageSubscriberNotificationLogRedaction.test.ts +54 -0
- package/Tests/Server/Services/StatusPageSubscriberNotificationTemplateCompile.test.ts +37 -0
- package/Tests/Server/Services/StatusPageSubscriberNotificationTemplateIncidentRecordAccess.test.ts +772 -0
- package/Tests/Server/Services/StatusPageSubscriberNotificationTemplateLookup.test.ts +506 -0
- package/Tests/Server/Services/StatusPageSubscriberNotificationTemplateLookupPostgres.test.ts +261 -0
- package/Tests/Server/Services/StatusPageSubscriberReport.test.ts +21 -5
- package/Tests/Server/Services/StatusPageSubscriberUnsubscribe.test.ts +1618 -0
- package/Tests/Server/Services/StatusPageSubscriberUnsubscribeLinkSenders.test.ts +373 -0
- package/Tests/Server/Services/StatusPageSubscriberUnsubscribePostgres.test.ts +388 -0
- package/Tests/Server/Services/SubscriberNotificationInFlightRequeue.test.ts +500 -0
- package/Tests/Server/Types/MarkdownEmailLinks.test.ts +320 -0
- package/Tests/Server/Types/Workflow/Components/Email.test.ts +491 -1
- package/Tests/Server/Types/Workflow/Components/EmailSmtpPinning.test.ts +398 -0
- package/Tests/Server/Utils/AffectedResources/LinkedAffectedResources.test.ts +858 -0
- package/Tests/Server/Utils/Alert/AlertStateChangeAuthorization.test.ts +1172 -0
- package/Tests/Server/Utils/CustomField/CustomFieldRename.test.ts +586 -0
- package/Tests/Server/Utils/DataSource/EgressGuard.test.ts +246 -10
- package/Tests/Server/Utils/DataSource/EgressGuardDeploymentConfig.test.ts +226 -0
- package/Tests/Server/Utils/DataSource/EgressGuardPinning.test.ts +131 -0
- package/Tests/Server/Utils/DataSource/HttpFetch.test.ts +4 -0
- package/Tests/Server/Utils/EgressPolicyEnvironment.ts +45 -0
- package/Tests/Server/Utils/Mail/PinnedSmtpSocket.test.ts +409 -0
- package/Tests/Server/Utils/Monitor/MonitorCriteriaObservationBuilderUnits.test.ts +23 -0
- package/Tests/Server/Utils/SSRFProtection.test.ts +4 -0
- package/Tests/Server/Utils/SSRFProtectionCloudServiceAddresses.test.ts +4 -0
- package/Tests/Server/Utils/SSRFProtectionPrivateNetwork.test.ts +4 -0
- package/Tests/Server/Utils/SSRFProtectionResolutionDetail.test.ts +314 -0
- package/Tests/Server/Utils/StatusPage/IncidentStatusPageScope.test.ts +1699 -0
- package/Tests/Server/Utils/StatusPage/IncidentStatusPageScopeQueriesPostgres.test.ts +508 -0
- package/Tests/Server/Utils/StatusPage/IncidentSubscriberAudienceCallerPermission.test.ts +246 -0
- package/Tests/Server/Utils/StatusPage/IncidentTemplateVariableBuilder.test.ts +1348 -0
- package/Tests/Server/Utils/StatusPage/StatusPageReadAccess.test.ts +221 -0
- package/Tests/Server/Utils/StatusPage/StatusPageSubscriberUnsubscribeNotice.test.ts +132 -0
- package/Tests/Server/Utils/StatusPage/StatusPageSubscriberUnsubscribeToken.test.ts +155 -0
- package/Tests/Server/Utils/StatusPage/SubscriberIncidentEmailBuilder.test.ts +708 -0
- package/Tests/Server/Utils/StatusPage/SubscriberNotificationClaim.test.ts +255 -0
- package/Tests/Server/Utils/StatusPage/SubscriberNotificationClaimPostgres.test.ts +528 -0
- package/Tests/Server/Utils/StatusPage/SubscriberNotificationDeliveryRecord.test.ts +1238 -0
- package/Tests/Server/Utils/StatusPage/SubscriberNotificationFanOut.test.ts +472 -0
- package/Tests/Server/Utils/StatusPage/SubscriberNotificationPreviewBuilder.test.ts +1168 -0
- package/Tests/Server/Utils/StatusPage/SubscriberNotificationRunLimit.test.ts +275 -0
- package/Tests/Server/Utils/StatusPage/SubscriberNotificationTiming.test.ts +131 -0
- package/Tests/Server/Utils/StatusPageResource.test.ts +98 -0
- package/Tests/Server/Utils/Topology/InventoryItemEntityKeyIndexMigration.test.ts +386 -0
- package/Tests/Server/Utils/Topology/InventoryItemEntityKeyIndexMigrationPostgres.test.ts +430 -0
- package/Tests/Server/Utils/Topology/TopologyActivityParityPostgres.test.ts +279 -0
- package/Tests/Server/Utils/Topology/TopologyConcurrencyLimiter.test.ts +534 -0
- package/Tests/Server/Utils/Topology/TopologyEstateGenerator.ts +624 -0
- package/Tests/Server/Utils/Topology/TopologyJsonResponse.test.ts +90 -0
- package/Tests/Server/Utils/Topology/TopologyQueries.test.ts +1634 -0
- package/Tests/Server/Utils/Topology/TopologyQueriesDifferentialPostgres.test.ts +683 -0
- package/Tests/Server/Utils/Topology/TopologyQueriesPostgres.test.ts +2624 -0
- package/Tests/Server/Utils/Topology/TopologyReference.ts +1018 -0
- package/Tests/Server/Utils/Topology/TopologyRequest.test.ts +643 -0
- package/Tests/Server/Utils/Topology/TopologyResponseCache.test.ts +305 -0
- package/Tests/Server/Utils/Topology/TopologySql.test.ts +973 -0
- package/Tests/Server/Utils/VM/VMRunnerPrivateNetworkWiring.test.ts +17 -0
- package/Tests/Server/Utils/VM/VMRunnerSsrf.test.ts +75 -0
- package/Tests/Types/CustomField/CustomFieldSavedViews.test.ts +247 -0
- package/Tests/Types/CustomField/CustomFieldTemplateValues.test.ts +186 -0
- package/Tests/Types/CustomField/CustomFieldTypeCorrespondence.test.ts +48 -0
- package/Tests/Types/CustomField/CustomFieldValueFormat.test.ts +215 -0
- package/Tests/Types/CustomField/CustomFieldValueValidator.test.ts +343 -0
- package/Tests/Types/CustomField/CustomFieldVariableKey.test.ts +364 -0
- package/Tests/Types/SafeHtml.test.ts +102 -0
- package/Tests/Types/StatusPage/IncidentCreatedRenotify.test.ts +419 -0
- package/Tests/Types/StatusPage/IncidentCreatedResend.test.ts +118 -0
- package/Tests/Types/StatusPage/IncidentScopeAddedPagesNotification.test.ts +558 -0
- package/Tests/Types/StatusPage/IncidentSubscriberAudience.test.ts +284 -0
- package/Tests/Types/StatusPage/StatusPageSubscriberUnsubscribe.test.ts +341 -0
- package/Tests/Types/StatusPage/SubscriberNotificationPreview.test.ts +196 -0
- package/Tests/Types/StatusPage/SubscriberNotificationResend.test.ts +201 -0
- package/Tests/Types/StatusPage/SubscriberNotificationTemplateCompiler.test.ts +277 -0
- package/Tests/Types/StatusPage/SubscriberNotificationTemplatePreview.test.ts +179 -0
- package/Tests/Types/StatusPage/SubscriberNotificationTemplateVariables.test.ts +324 -0
- package/Tests/Types/StatusPage/SubscriberUpdateNotification.test.ts +60 -13
- package/Tests/Types/Topology/TopologyTypeRules.test.ts +176 -0
- package/Tests/UI/Components/CustomFields/CustomFieldFormFields.test.ts +432 -0
- package/Tests/UI/Components/CustomFields/CustomFieldModelFormFields.test.tsx +685 -0
- package/Tests/UI/Components/CustomFields/CustomFieldsDetailOrder.test.tsx +469 -0
- package/Tests/UI/Components/Forms/ModelFormCustomFieldInputs.test.tsx +325 -0
- package/Tests/UI/Components/Forms/ModelFormDropdownOptionsRefused.test.tsx +358 -0
- package/Tests/UI/Components/ModelTable/CustomFieldColumns.test.tsx +22 -0
- package/Tests/UI/Monitor/NetworkPathView.test.tsx +289 -0
- package/Tests/Utils/Incident/IncidentFromAlerts.test.ts +302 -0
- package/Tests/Utils/Incident/IncidentNoteTemplateVariables.test.ts +623 -0
- package/Tests/Utils/Markdown/MarkdownEscape.test.ts +89 -0
- package/Tests/Utils/ProbeNetworkFailureUtil.test.ts +992 -0
- package/Tests/Utils/RequestFailedDetails.test.ts +575 -0
- package/Types/CustomField/CustomFieldOrder.ts +55 -0
- package/Types/CustomField/CustomFieldSavedViews.ts +225 -0
- package/Types/CustomField/CustomFieldTemplateMerge.ts +71 -0
- package/Types/CustomField/CustomFieldType.ts +14 -0
- package/Types/CustomField/CustomFieldValueFormat.ts +161 -0
- package/Types/CustomField/CustomFieldValueValidator.ts +488 -0
- package/Types/CustomField/CustomFieldVariableKey.ts +211 -0
- package/Types/Incident/IncidentAlertLink.ts +19 -0
- package/Types/SafeHtml.ts +93 -0
- package/Types/StatusPage/IncidentCreatedRenotify.ts +224 -0
- package/Types/StatusPage/IncidentCreatedResend.ts +108 -0
- package/Types/StatusPage/IncidentScopeAddedPagesNotification.ts +343 -0
- package/Types/StatusPage/IncidentSubscriberAudience.ts +332 -0
- package/Types/StatusPage/StatusPageSubscriberUnsubscribe.ts +405 -0
- package/Types/StatusPage/SubscriberNotificationInterruption.ts +32 -0
- package/Types/StatusPage/SubscriberNotificationPreview.ts +322 -0
- package/Types/StatusPage/SubscriberNotificationResend.ts +132 -0
- package/Types/StatusPage/SubscriberNotificationTemplateCompiler.ts +180 -0
- package/Types/StatusPage/SubscriberNotificationTemplatePreview.ts +301 -0
- package/Types/StatusPage/SubscriberNotificationTemplateVariables.ts +217 -4
- package/Types/StatusPage/SubscriberUpdateNotification.ts +32 -11
- package/Types/Telemetry/InventoryLiveness.ts +26 -0
- package/Types/Topology/TopologyApi.ts +428 -0
- package/Types/Topology/TopologyTypeRules.ts +191 -0
- package/UI/Components/CustomFields/CustomFieldFormFields.ts +317 -0
- package/UI/Components/CustomFields/CustomFieldModelFormFields.tsx +395 -0
- package/UI/Components/CustomFields/CustomFieldsDetail.tsx +95 -55
- package/UI/Components/Forms/ModelForm.tsx +70 -8
- package/UI/Components/Forms/Validation.ts +1 -1
- package/UI/Components/ModelFormModal/ModelFormModal.tsx +2 -4
- package/UI/Components/ModelTable/AnalyticsModelTable.tsx +2 -6
- package/UI/Components/ModelTable/BaseModelTable.tsx +9 -8
- package/UI/Components/ModelTable/CustomFieldColumns.tsx +14 -1
- package/UI/Components/ModelTable/ModelTable.tsx +6 -7
- package/UI/Utils/SensitiveUrlToken.ts +10 -5
- package/Utils/API.ts +247 -2
- package/Utils/Incident/IncidentFromAlerts.ts +78 -0
- package/Utils/Incident/IncidentNoteTemplateVariables.ts +304 -0
- package/Utils/Markdown/MarkdownEscape.ts +65 -0
- package/Utils/ProbeNetworkFailureUtil.ts +673 -0
- package/build/dist/Models/DatabaseModels/Incident.js +267 -1
- package/build/dist/Models/DatabaseModels/Incident.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentCustomField.js +207 -1
- package/build/dist/Models/DatabaseModels/IncidentCustomField.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentEpisode.js +31 -0
- package/build/dist/Models/DatabaseModels/IncidentEpisode.js.map +1 -1
- package/build/dist/Models/DatabaseModels/IncidentTemplate.js +124 -1
- package/build/dist/Models/DatabaseModels/IncidentTemplate.js.map +1 -1
- package/build/dist/Models/DatabaseModels/InventoryItem.js +20 -11
- package/build/dist/Models/DatabaseModels/InventoryItem.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPage.js +56 -0
- package/build/dist/Models/DatabaseModels/StatusPage.js.map +1 -1
- package/build/dist/Models/DatabaseModels/StatusPageSubscriber.js +131 -0
- package/build/dist/Models/DatabaseModels/StatusPageSubscriber.js.map +1 -1
- package/build/dist/Server/API/IncidentAPI.js +100 -1
- package/build/dist/Server/API/IncidentAPI.js.map +1 -1
- package/build/dist/Server/API/StatusPageAPI.js +417 -176
- package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
- package/build/dist/Server/API/StatusPageSubscriberAPI.js +52 -13
- package/build/dist/Server/API/StatusPageSubscriberAPI.js.map +1 -1
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795200000000-AddInventoryItemProjectEntityKeyIndex.js +165 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795200000000-AddInventoryItemProjectEntityKeyIndex.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795300000000-SkipHiddenIncidentCreatedNotifications.js +41 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795300000000-SkipHiddenIncidentCreatedNotifications.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795400000000-AddIncidentStatusPageScope.js +57 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795400000000-AddIncidentStatusPageScope.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795500000000-AddIncidentTemplateStatusPageScopeFlag.js +23 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795500000000-AddIncidentTemplateStatusPageScopeFlag.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795600000000-AddStatusPageSubscriberUnsubscribeToken.js +40 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795600000000-AddStatusPageSubscriberUnsubscribeToken.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795700000000-AddStatusPageSubscriberIsAddedByTeam.js +26 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795700000000-AddStatusPageSubscriberIsAddedByTeam.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795800000000-AddIncidentCustomFieldCreateAndNotificationSettings.js +89 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795800000000-AddIncidentCustomFieldCreateAndNotificationSettings.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795900000000-AddSubscriberNotificationClaimedAt.js +29 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795900000000-AddSubscriberNotificationClaimedAt.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +16 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Infrastructure/Semaphore.js +3 -0
- package/build/dist/Server/Infrastructure/Semaphore.js.map +1 -1
- package/build/dist/Server/Middleware/IdentityRateLimit.js +89 -3
- package/build/dist/Server/Middleware/IdentityRateLimit.js.map +1 -1
- package/build/dist/Server/Middleware/SubscriberNotificationPreviewRateLimit.js +149 -0
- package/build/dist/Server/Middleware/SubscriberNotificationPreviewRateLimit.js.map +1 -0
- package/build/dist/Server/Middleware/SubscriberNotificationTestSendRateLimit.js +190 -0
- package/build/dist/Server/Middleware/SubscriberNotificationTestSendRateLimit.js.map +1 -0
- package/build/dist/Server/Services/AlertService.js +21 -33
- package/build/dist/Server/Services/AlertService.js.map +1 -1
- package/build/dist/Server/Services/DatabaseService.js +56 -7
- package/build/dist/Server/Services/DatabaseService.js.map +1 -1
- package/build/dist/Server/Services/IncidentAlertService.js +457 -3
- package/build/dist/Server/Services/IncidentAlertService.js.map +1 -1
- package/build/dist/Server/Services/IncidentCustomFieldService.js +204 -8
- package/build/dist/Server/Services/IncidentCustomFieldService.js.map +1 -1
- package/build/dist/Server/Services/IncidentEpisodePublicNoteService.js +24 -0
- package/build/dist/Server/Services/IncidentEpisodePublicNoteService.js.map +1 -1
- package/build/dist/Server/Services/IncidentEpisodeService.js +14 -0
- package/build/dist/Server/Services/IncidentEpisodeService.js.map +1 -1
- package/build/dist/Server/Services/IncidentEpisodeStateTimelineService.js +26 -0
- package/build/dist/Server/Services/IncidentEpisodeStateTimelineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentPublicNoteService.js +26 -1
- package/build/dist/Server/Services/IncidentPublicNoteService.js.map +1 -1
- package/build/dist/Server/Services/IncidentService.js +1148 -42
- package/build/dist/Server/Services/IncidentService.js.map +1 -1
- package/build/dist/Server/Services/IncidentStateTimelineService.js +12 -0
- package/build/dist/Server/Services/IncidentStateTimelineService.js.map +1 -1
- package/build/dist/Server/Services/IncidentTemplateService.js +83 -0
- package/build/dist/Server/Services/IncidentTemplateService.js.map +1 -1
- package/build/dist/Server/Services/InventoryItemService.js +31 -0
- package/build/dist/Server/Services/InventoryItemService.js.map +1 -1
- package/build/dist/Server/Services/IoTDeviceCredentialService.js +12 -5
- package/build/dist/Server/Services/IoTDeviceCredentialService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenancePublicNoteService.js +26 -1
- package/build/dist/Server/Services/ScheduledMaintenancePublicNoteService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenanceService.js +84 -57
- package/build/dist/Server/Services/ScheduledMaintenanceService.js.map +1 -1
- package/build/dist/Server/Services/SmsService.js +2 -22
- package/build/dist/Server/Services/SmsService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageService.js +47 -9
- package/build/dist/Server/Services/StatusPageService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageSubscriberNotificationTemplateService.js +237 -32
- package/build/dist/Server/Services/StatusPageSubscriberNotificationTemplateService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageSubscriberNotificationTemplateStatusPageService.js +109 -0
- package/build/dist/Server/Services/StatusPageSubscriberNotificationTemplateStatusPageService.js.map +1 -1
- package/build/dist/Server/Services/StatusPageSubscriberService.js +925 -99
- package/build/dist/Server/Services/StatusPageSubscriberService.js.map +1 -1
- package/build/dist/Server/Services/UserNotificationRuleService.js +55 -51
- package/build/dist/Server/Services/UserNotificationRuleService.js.map +1 -1
- package/build/dist/Server/Services/WorkspaceNotificationSummaryService.js +42 -25
- package/build/dist/Server/Services/WorkspaceNotificationSummaryService.js.map +1 -1
- package/build/dist/Server/Types/Markdown.js +110 -6
- package/build/dist/Server/Types/Markdown.js.map +1 -1
- package/build/dist/Server/Types/Workflow/Components/Email.js +55 -6
- package/build/dist/Server/Types/Workflow/Components/Email.js.map +1 -1
- package/build/dist/Server/Utils/AffectedResources/LinkedAffectedResources.js +405 -0
- package/build/dist/Server/Utils/AffectedResources/LinkedAffectedResources.js.map +1 -0
- package/build/dist/Server/Utils/Alert/AlertStateChangeAuthorization.js +112 -0
- package/build/dist/Server/Utils/Alert/AlertStateChangeAuthorization.js.map +1 -0
- package/build/dist/Server/Utils/CustomField/CustomFieldRename.js +211 -0
- package/build/dist/Server/Utils/CustomField/CustomFieldRename.js.map +1 -0
- package/build/dist/Server/Utils/DataSource/EgressGuard.js +41 -12
- package/build/dist/Server/Utils/DataSource/EgressGuard.js.map +1 -1
- package/build/dist/Server/Utils/Inventory/InventoryOverviewAggregation.js +81 -0
- package/build/dist/Server/Utils/Inventory/InventoryOverviewAggregation.js.map +1 -0
- package/build/dist/Server/Utils/Mail/PinnedSmtpSocket.js +101 -0
- package/build/dist/Server/Utils/Mail/PinnedSmtpSocket.js.map +1 -0
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.js +9 -0
- package/build/dist/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.js.map +1 -1
- package/build/dist/Server/Utils/Response.js +30 -0
- package/build/dist/Server/Utils/Response.js.map +1 -1
- package/build/dist/Server/Utils/SSRFProtection.js +48 -6
- package/build/dist/Server/Utils/SSRFProtection.js.map +1 -1
- package/build/dist/Server/Utils/StatusPage/IncidentStatusPageScope.js +631 -0
- package/build/dist/Server/Utils/StatusPage/IncidentStatusPageScope.js.map +1 -0
- package/build/dist/Server/Utils/StatusPage/IncidentSubscriberAudienceBuilder.js +403 -0
- package/build/dist/Server/Utils/StatusPage/IncidentSubscriberAudienceBuilder.js.map +1 -0
- package/build/dist/Server/Utils/StatusPage/IncidentTemplateVariableBuilder.js +451 -0
- package/build/dist/Server/Utils/StatusPage/IncidentTemplateVariableBuilder.js.map +1 -0
- package/build/dist/Server/Utils/StatusPage/StatusPageExclusion.js +13 -0
- package/build/dist/Server/Utils/StatusPage/StatusPageExclusion.js.map +1 -0
- package/build/dist/Server/Utils/StatusPage/StatusPageReadAccess.js +91 -0
- package/build/dist/Server/Utils/StatusPage/StatusPageReadAccess.js.map +1 -0
- package/build/dist/Server/Utils/StatusPage/StatusPageSubscriberUnsubscribeNotice.js +101 -0
- package/build/dist/Server/Utils/StatusPage/StatusPageSubscriberUnsubscribeNotice.js.map +1 -0
- package/build/dist/Server/Utils/StatusPage/StatusPageSubscriberUnsubscribeToken.js +47 -0
- package/build/dist/Server/Utils/StatusPage/StatusPageSubscriberUnsubscribeToken.js.map +1 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberIncidentEmailBuilder.js +273 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberIncidentEmailBuilder.js.map +1 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberNotificationClaim.js +73 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberNotificationClaim.js.map +1 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberNotificationDeliveryRecord.js +722 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberNotificationDeliveryRecord.js.map +1 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberNotificationFanOut.js +102 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberNotificationFanOut.js.map +1 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberNotificationPreviewBuilder.js +527 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberNotificationPreviewBuilder.js.map +1 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberNotificationResendAccess.js +278 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberNotificationResendAccess.js.map +1 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberNotificationRunLimit.js +137 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberNotificationRunLimit.js.map +1 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberNotificationTiming.js +103 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberNotificationTiming.js.map +1 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberTemplateIncidentRecordAccess.js +114 -0
- package/build/dist/Server/Utils/StatusPage/SubscriberTemplateIncidentRecordAccess.js.map +1 -0
- package/build/dist/Server/Utils/StatusPageResource.js +39 -7
- package/build/dist/Server/Utils/StatusPageResource.js.map +1 -1
- package/build/dist/Server/Utils/Topology/TopologyConcurrencyLimiter.js +178 -0
- package/build/dist/Server/Utils/Topology/TopologyConcurrencyLimiter.js.map +1 -0
- package/build/dist/Server/Utils/Topology/TopologyQueries.js +884 -0
- package/build/dist/Server/Utils/Topology/TopologyQueries.js.map +1 -0
- package/build/dist/Server/Utils/Topology/TopologyRequest.js +275 -0
- package/build/dist/Server/Utils/Topology/TopologyRequest.js.map +1 -0
- package/build/dist/Server/Utils/Topology/TopologyResponseCache.js +146 -0
- package/build/dist/Server/Utils/Topology/TopologyResponseCache.js.map +1 -0
- package/build/dist/Server/Utils/Topology/TopologySql.js +688 -0
- package/build/dist/Server/Utils/Topology/TopologySql.js.map +1 -0
- package/build/dist/Server/Utils/VM/VMAPI.js.map +1 -1
- package/build/dist/Server/Utils/VM/VMRunner.js +1 -0
- package/build/dist/Server/Utils/VM/VMRunner.js.map +1 -1
- package/build/dist/Server/Utils/Workflow/OAuth2TokenClient.js +3 -0
- package/build/dist/Server/Utils/Workflow/OAuth2TokenClient.js.map +1 -1
- package/build/dist/Types/CustomField/CustomFieldOrder.js +36 -0
- package/build/dist/Types/CustomField/CustomFieldOrder.js.map +1 -0
- package/build/dist/Types/CustomField/CustomFieldSavedViews.js +135 -0
- package/build/dist/Types/CustomField/CustomFieldSavedViews.js.map +1 -0
- package/build/dist/Types/CustomField/CustomFieldTemplateMerge.js +27 -0
- package/build/dist/Types/CustomField/CustomFieldTemplateMerge.js.map +1 -0
- package/build/dist/Types/CustomField/CustomFieldType.js +12 -0
- package/build/dist/Types/CustomField/CustomFieldType.js.map +1 -1
- package/build/dist/Types/CustomField/CustomFieldValueFormat.js +126 -0
- package/build/dist/Types/CustomField/CustomFieldValueFormat.js.map +1 -0
- package/build/dist/Types/CustomField/CustomFieldValueValidator.js +280 -0
- package/build/dist/Types/CustomField/CustomFieldValueValidator.js.map +1 -0
- package/build/dist/Types/CustomField/CustomFieldVariableKey.js +150 -0
- package/build/dist/Types/CustomField/CustomFieldVariableKey.js.map +1 -0
- package/build/dist/Types/Incident/IncidentAlertLink.js +17 -0
- package/build/dist/Types/Incident/IncidentAlertLink.js.map +1 -1
- package/build/dist/Types/SafeHtml.js +84 -0
- package/build/dist/Types/SafeHtml.js.map +1 -0
- package/build/dist/Types/StatusPage/IncidentCreatedRenotify.js +117 -0
- package/build/dist/Types/StatusPage/IncidentCreatedRenotify.js.map +1 -0
- package/build/dist/Types/StatusPage/IncidentCreatedResend.js +86 -0
- package/build/dist/Types/StatusPage/IncidentCreatedResend.js.map +1 -0
- package/build/dist/Types/StatusPage/IncidentScopeAddedPagesNotification.js +246 -0
- package/build/dist/Types/StatusPage/IncidentScopeAddedPagesNotification.js.map +1 -0
- package/build/dist/Types/StatusPage/IncidentSubscriberAudience.js +183 -0
- package/build/dist/Types/StatusPage/IncidentSubscriberAudience.js.map +1 -0
- package/build/dist/Types/StatusPage/StatusPageSubscriberUnsubscribe.js +277 -0
- package/build/dist/Types/StatusPage/StatusPageSubscriberUnsubscribe.js.map +1 -0
- package/build/dist/Types/StatusPage/SubscriberNotificationInterruption.js +27 -0
- package/build/dist/Types/StatusPage/SubscriberNotificationInterruption.js.map +1 -0
- package/build/dist/Types/StatusPage/SubscriberNotificationPreview.js +190 -0
- package/build/dist/Types/StatusPage/SubscriberNotificationPreview.js.map +1 -0
- package/build/dist/Types/StatusPage/SubscriberNotificationResend.js +102 -0
- package/build/dist/Types/StatusPage/SubscriberNotificationResend.js.map +1 -0
- package/build/dist/Types/StatusPage/SubscriberNotificationTemplateCompiler.js +97 -0
- package/build/dist/Types/StatusPage/SubscriberNotificationTemplateCompiler.js.map +1 -0
- package/build/dist/Types/StatusPage/SubscriberNotificationTemplatePreview.js +175 -0
- package/build/dist/Types/StatusPage/SubscriberNotificationTemplatePreview.js.map +1 -0
- package/build/dist/Types/StatusPage/SubscriberNotificationTemplateVariables.js +144 -4
- package/build/dist/Types/StatusPage/SubscriberNotificationTemplateVariables.js.map +1 -1
- package/build/dist/Types/StatusPage/SubscriberUpdateNotification.js +29 -9
- package/build/dist/Types/StatusPage/SubscriberUpdateNotification.js.map +1 -1
- package/build/dist/Types/Telemetry/InventoryLiveness.js +23 -0
- package/build/dist/Types/Telemetry/InventoryLiveness.js.map +1 -1
- package/build/dist/Types/Topology/TopologyApi.js +55 -0
- package/build/dist/Types/Topology/TopologyApi.js.map +1 -0
- package/build/dist/Types/Topology/TopologyTypeRules.js +165 -0
- package/build/dist/Types/Topology/TopologyTypeRules.js.map +1 -0
- package/build/dist/UI/Components/CustomFields/CustomFieldFormFields.js +169 -0
- package/build/dist/UI/Components/CustomFields/CustomFieldFormFields.js.map +1 -0
- package/build/dist/UI/Components/CustomFields/CustomFieldModelFormFields.js +212 -0
- package/build/dist/UI/Components/CustomFields/CustomFieldModelFormFields.js.map +1 -0
- package/build/dist/UI/Components/CustomFields/CustomFieldsDetail.js +64 -49
- package/build/dist/UI/Components/CustomFields/CustomFieldsDetail.js.map +1 -1
- package/build/dist/UI/Components/Forms/ModelForm.js +39 -5
- package/build/dist/UI/Components/Forms/ModelForm.js.map +1 -1
- package/build/dist/UI/Components/Forms/Validation.js +1 -1
- package/build/dist/UI/Components/Forms/Validation.js.map +1 -1
- package/build/dist/UI/Components/ModelFormModal/ModelFormModal.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/AnalyticsModelTable.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js +2 -2
- package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/CustomFieldColumns.js +13 -1
- package/build/dist/UI/Components/ModelTable/CustomFieldColumns.js.map +1 -1
- package/build/dist/UI/Components/ModelTable/ModelTable.js +1 -1
- package/build/dist/UI/Components/ModelTable/ModelTable.js.map +1 -1
- package/build/dist/UI/Utils/SensitiveUrlToken.js +10 -5
- package/build/dist/UI/Utils/SensitiveUrlToken.js.map +1 -1
- package/build/dist/Utils/API.js +177 -1
- package/build/dist/Utils/API.js.map +1 -1
- package/build/dist/Utils/Incident/IncidentFromAlerts.js +38 -0
- package/build/dist/Utils/Incident/IncidentFromAlerts.js.map +1 -1
- package/build/dist/Utils/Incident/IncidentNoteTemplateVariables.js +155 -0
- package/build/dist/Utils/Incident/IncidentNoteTemplateVariables.js.map +1 -0
- package/build/dist/Utils/Markdown/MarkdownEscape.js +48 -0
- package/build/dist/Utils/Markdown/MarkdownEscape.js.map +1 -1
- package/build/dist/Utils/ProbeNetworkFailureUtil.js +460 -0
- package/build/dist/Utils/ProbeNetworkFailureUtil.js.map +1 -0
- package/package.json +1 -1
|
@@ -87,9 +87,20 @@ const FOREIGN_KEY_COLUMNS: Array<Array<string>> = [
|
|
|
87
87
|
["deletedByUserId"],
|
|
88
88
|
];
|
|
89
89
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
90
|
+
interface DeclaredIndex {
|
|
91
|
+
columns: Array<string>;
|
|
92
|
+
/*
|
|
93
|
+
* The name the model pins with `@Index("NAME", [...])`, when it pins one.
|
|
94
|
+
*
|
|
95
|
+
* Only TypeORM's derived names contain the table name and so had to be
|
|
96
|
+
* renamed. A pinned name reads the same before and after the rename, so the
|
|
97
|
+
* rename has nothing to do for it - and must not claim to, or it would try
|
|
98
|
+
* to rename a name that never existed.
|
|
99
|
+
*/
|
|
100
|
+
name: string | undefined;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
type DeclaredIndexesFunction = (modelType: ModelClass) => Array<DeclaredIndex>;
|
|
93
104
|
|
|
94
105
|
/*
|
|
95
106
|
* The indexes a model actually declares, read out of TypeORM's decorator
|
|
@@ -97,19 +108,19 @@ type DeclaredIndexColumnsFunction = (
|
|
|
97
108
|
* `@Index([...])` carries its columns; a column-level `@Index()` records the
|
|
98
109
|
* property it decorates instead.
|
|
99
110
|
*/
|
|
100
|
-
const
|
|
111
|
+
const getDeclaredIndexes: DeclaredIndexesFunction = (
|
|
101
112
|
modelType: ModelClass,
|
|
102
|
-
): Array<
|
|
113
|
+
): Array<DeclaredIndex> => {
|
|
103
114
|
return getMetadataArgsStorage()
|
|
104
115
|
.indices.filter((index: IndexMetadataArgs): boolean => {
|
|
105
116
|
return index.target === modelType;
|
|
106
117
|
})
|
|
107
|
-
.map((index: IndexMetadataArgs):
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
118
|
+
.map((index: IndexMetadataArgs): DeclaredIndex => {
|
|
119
|
+
const columns: Array<string> = Array.isArray(index.columns)
|
|
120
|
+
? (index.columns as Array<string>)
|
|
121
|
+
: [String((index as { propertyName?: string }).propertyName)];
|
|
111
122
|
|
|
112
|
-
return
|
|
123
|
+
return { columns: columns, name: index.name };
|
|
113
124
|
});
|
|
114
125
|
};
|
|
115
126
|
|
|
@@ -145,9 +156,10 @@ const MIGRATION_TIMESTAMP: number = 1786800000000;
|
|
|
145
156
|
* yet. Read out of the migration directory rather than hand-listed, so a
|
|
146
157
|
* future migration adding an index does not require editing this test.
|
|
147
158
|
*/
|
|
148
|
-
|
|
159
|
+
/** The source of every migration that runs after the rename. */
|
|
160
|
+
function getMigrationSourcesAfterTheRename(): Array<string> {
|
|
149
161
|
const directory: string = path.dirname(MIGRATION_PATH);
|
|
150
|
-
const
|
|
162
|
+
const sources: Array<string> = [];
|
|
151
163
|
|
|
152
164
|
for (const file of fs.readdirSync(directory)) {
|
|
153
165
|
const timestamp: number = Number(file.split("-")[0]);
|
|
@@ -156,11 +168,27 @@ function getIndexesCreatedAfterTheRename(): Set<string> {
|
|
|
156
168
|
continue;
|
|
157
169
|
}
|
|
158
170
|
|
|
159
|
-
|
|
171
|
+
sources.push(fs.readFileSync(path.join(directory, file), "utf8"));
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
return sources;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
const MIGRATIONS_AFTER_THE_RENAME: Array<string> =
|
|
178
|
+
getMigrationSourcesAfterTheRename();
|
|
179
|
+
|
|
180
|
+
function getIndexesCreatedAfterTheRename(): Set<string> {
|
|
181
|
+
const created: Set<string> = new Set<string>();
|
|
160
182
|
|
|
183
|
+
for (const source of MIGRATIONS_AFTER_THE_RENAME) {
|
|
161
184
|
for (const table of ["InventoryItem", "InventoryItemRelationship"]) {
|
|
185
|
+
/*
|
|
186
|
+
* `IF NOT EXISTS` is allowed for: a migration that has to be safe to
|
|
187
|
+
* re-run still creates the index, and skipping it here would demand a
|
|
188
|
+
* rename pair for an index that did not exist when the rename ran.
|
|
189
|
+
*/
|
|
162
190
|
const pattern: RegExp = new RegExp(
|
|
163
|
-
`CREATE (?:UNIQUE )?INDEX "(IDX_[a-f0-9]+)" ON "${table}"`,
|
|
191
|
+
`CREATE (?:UNIQUE )?INDEX (?:IF NOT EXISTS )?"(IDX_[a-f0-9]+)" ON "${table}"`,
|
|
164
192
|
"g",
|
|
165
193
|
);
|
|
166
194
|
|
|
@@ -178,6 +206,23 @@ function getIndexesCreatedAfterTheRename(): Set<string> {
|
|
|
178
206
|
|
|
179
207
|
const INDEXES_ADDED_LATER: Set<string> = getIndexesCreatedAfterTheRename();
|
|
180
208
|
|
|
209
|
+
type PinnedIndexCreatedFunction = (indexName: string) => boolean;
|
|
210
|
+
|
|
211
|
+
/*
|
|
212
|
+
* Whether some migration after the rename creates the index a model pins by
|
|
213
|
+
* name. Matched by the name appearing anywhere in that migration rather than
|
|
214
|
+
* by a CREATE INDEX pattern: a pinned name is normally held in an exported
|
|
215
|
+
* constant and interpolated into the statement, so the statement itself
|
|
216
|
+
* carries `${THE_CONSTANT}` and only the declaration carries the literal.
|
|
217
|
+
*/
|
|
218
|
+
const isPinnedIndexCreatedAfterTheRename: PinnedIndexCreatedFunction = (
|
|
219
|
+
indexName: string,
|
|
220
|
+
): boolean => {
|
|
221
|
+
return MIGRATIONS_AFTER_THE_RENAME.some((source: string): boolean => {
|
|
222
|
+
return source.includes(indexName);
|
|
223
|
+
});
|
|
224
|
+
};
|
|
225
|
+
|
|
181
226
|
type PairMapFunction = (prefix: string) => Map<string, string>;
|
|
182
227
|
|
|
183
228
|
const pairsWithPrefix: PairMapFunction = (
|
|
@@ -228,15 +273,34 @@ describe("the data survives", () => {
|
|
|
228
273
|
|
|
229
274
|
describe("index names match TypeORM's naming strategy", () => {
|
|
230
275
|
for (const table of TABLES) {
|
|
231
|
-
const declared: Array<
|
|
232
|
-
table.modelType,
|
|
233
|
-
);
|
|
276
|
+
const declared: Array<DeclaredIndex> = getDeclaredIndexes(table.modelType);
|
|
234
277
|
|
|
235
278
|
test(`${table.newTable} declares indexes to rename`, () => {
|
|
236
279
|
expect(declared.length).toBeGreaterThan(0);
|
|
237
280
|
});
|
|
238
281
|
|
|
239
|
-
for (const
|
|
282
|
+
for (const index of declared) {
|
|
283
|
+
const columns: Array<string> = index.columns;
|
|
284
|
+
const pinnedName: string | undefined = index.name;
|
|
285
|
+
|
|
286
|
+
if (pinnedName) {
|
|
287
|
+
/*
|
|
288
|
+
* A pinned name carries no table name, so the rename had nothing to
|
|
289
|
+
* change and must not claim otherwise. What still has to hold is that
|
|
290
|
+
* a migration creates it - otherwise the model declares an index that
|
|
291
|
+
* only ever exists on a schema the builder synchronizes, and these are
|
|
292
|
+
* declared `synchronize: false` precisely so it does not.
|
|
293
|
+
*/
|
|
294
|
+
test(`${table.newTable} (${columns.join(", ")}) is pinned by name, so the rename leaves it alone`, () => {
|
|
295
|
+
const indexPairs: Map<string, string> = pairsWithPrefix("IDX_");
|
|
296
|
+
|
|
297
|
+
expect(indexPairs.has(pinnedName)).toBe(false);
|
|
298
|
+
expect(Array.from(indexPairs.values())).not.toContain(pinnedName);
|
|
299
|
+
expect(isPinnedIndexCreatedAfterTheRename(pinnedName)).toBe(true);
|
|
300
|
+
});
|
|
301
|
+
continue;
|
|
302
|
+
}
|
|
303
|
+
|
|
240
304
|
const oldName: string = namingStrategy.indexName(table.oldTable, columns);
|
|
241
305
|
const newName: string = namingStrategy.indexName(table.newTable, columns);
|
|
242
306
|
|
|
@@ -263,16 +327,21 @@ describe("index names match TypeORM's naming strategy", () => {
|
|
|
263
327
|
const expected: Set<string> = new Set<string>();
|
|
264
328
|
|
|
265
329
|
for (const table of TABLES) {
|
|
266
|
-
for (const
|
|
330
|
+
for (const index of getDeclaredIndexes(table.modelType)) {
|
|
331
|
+
if (index.name) {
|
|
332
|
+
// Pinned name: table-independent, so the rename never touched it.
|
|
333
|
+
continue;
|
|
334
|
+
}
|
|
335
|
+
|
|
267
336
|
if (
|
|
268
337
|
INDEXES_ADDED_LATER.has(
|
|
269
|
-
namingStrategy.indexName(table.newTable, columns),
|
|
338
|
+
namingStrategy.indexName(table.newTable, index.columns),
|
|
270
339
|
)
|
|
271
340
|
) {
|
|
272
341
|
continue;
|
|
273
342
|
}
|
|
274
343
|
|
|
275
|
-
expected.add(namingStrategy.indexName(table.oldTable, columns));
|
|
344
|
+
expected.add(namingStrategy.indexName(table.oldTable, index.columns));
|
|
276
345
|
}
|
|
277
346
|
}
|
|
278
347
|
|
package/Tests/Server/Infrastructure/Postgres/SkipHiddenIncidentCreatedNotificationsMigration.test.ts
ADDED
|
@@ -0,0 +1,410 @@
|
|
|
1
|
+
import Incident from "../../../../Models/DatabaseModels/Incident";
|
|
2
|
+
import {
|
|
3
|
+
HIDDEN_FROM_STATUS_PAGES_MESSAGE,
|
|
4
|
+
SkipHiddenIncidentCreatedNotifications1795300000000,
|
|
5
|
+
} from "../../../../Server/Infrastructure/Postgres/SchemaMigrations/1795300000000-SkipHiddenIncidentCreatedNotifications";
|
|
6
|
+
import SchemaMigrations from "../../../../Server/Infrastructure/Postgres/SchemaMigrations/Index";
|
|
7
|
+
import ObjectID from "../../../../Types/ObjectID";
|
|
8
|
+
import IncidentCreatedRenotify from "../../../../Types/StatusPage/IncidentCreatedRenotify";
|
|
9
|
+
import StatusPageSubscriberNotificationStatus from "../../../../Types/StatusPage/StatusPageSubscriberNotificationStatus";
|
|
10
|
+
import {
|
|
11
|
+
afterAll,
|
|
12
|
+
afterEach,
|
|
13
|
+
beforeAll,
|
|
14
|
+
beforeEach,
|
|
15
|
+
describe,
|
|
16
|
+
expect,
|
|
17
|
+
test,
|
|
18
|
+
} from "@jest/globals";
|
|
19
|
+
import {
|
|
20
|
+
DataSource,
|
|
21
|
+
MigrationInterface,
|
|
22
|
+
QueryRunner,
|
|
23
|
+
getMetadataArgsStorage,
|
|
24
|
+
} from "typeorm";
|
|
25
|
+
import type { ColumnMetadataArgs } from "typeorm/metadata-args/ColumnMetadataArgs";
|
|
26
|
+
|
|
27
|
+
/*
|
|
28
|
+
* SkipHiddenIncidentCreatedNotifications1795300000000 settles the 'incident
|
|
29
|
+
* created' subscriber notification of hidden incidents that the old worker
|
|
30
|
+
* marked InProgress and then abandoned. The worker only picks up Pending
|
|
31
|
+
* rows, so those rows could never move again; Skipped is what the fixed
|
|
32
|
+
* worker writes for a hidden incident, and what lets publishing the incident
|
|
33
|
+
* re-queue the notification.
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
interface Statement {
|
|
37
|
+
sql: string;
|
|
38
|
+
parameters: Array<unknown> | undefined;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
async function statementsFor(
|
|
42
|
+
direction: "up" | "down",
|
|
43
|
+
): Promise<Array<Statement>> {
|
|
44
|
+
const statements: Array<Statement> = [];
|
|
45
|
+
const runner: QueryRunner = {
|
|
46
|
+
query: async (sql: string, parameters?: Array<unknown>): Promise<void> => {
|
|
47
|
+
statements.push({ sql, parameters });
|
|
48
|
+
},
|
|
49
|
+
} as unknown as QueryRunner;
|
|
50
|
+
|
|
51
|
+
await new SkipHiddenIncidentCreatedNotifications1795300000000()[direction](
|
|
52
|
+
runner,
|
|
53
|
+
);
|
|
54
|
+
return statements;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function incidentColumn(property: string): ColumnMetadataArgs {
|
|
58
|
+
const column: ColumnMetadataArgs | undefined = getMetadataArgsStorage()
|
|
59
|
+
.columns.filter((args: ColumnMetadataArgs) => {
|
|
60
|
+
return args.target === Incident && args.propertyName === property;
|
|
61
|
+
})
|
|
62
|
+
.pop();
|
|
63
|
+
|
|
64
|
+
expect(column).toBeDefined();
|
|
65
|
+
return column!;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
describe("SkipHiddenIncidentCreatedNotifications1795300000000 SQL contract", () => {
|
|
69
|
+
test("up() runs a single UPDATE of Incident and no schema change", async () => {
|
|
70
|
+
const statements: Array<Statement> = await statementsFor("up");
|
|
71
|
+
|
|
72
|
+
expect(statements).toHaveLength(1);
|
|
73
|
+
expect(statements[0]!.sql).toMatch(/^UPDATE "Incident" SET /);
|
|
74
|
+
// Keywords only: the status column's own name contains "Created".
|
|
75
|
+
expect(statements[0]!.sql).not.toMatch(
|
|
76
|
+
/\b(ALTER|CREATE|DROP|DELETE|INSERT|TRUNCATE)\b/,
|
|
77
|
+
);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
test("sets the status to Skipped and the message to the worker's hidden-incident reason", async () => {
|
|
81
|
+
const statement: Statement = (await statementsFor("up"))[0]!;
|
|
82
|
+
|
|
83
|
+
expect(statement.sql).toContain(
|
|
84
|
+
`SET "subscriberNotificationStatusOnIncidentCreated" = '${StatusPageSubscriberNotificationStatus.Skipped}', "subscriberNotificationStatusMessage" = $1 `,
|
|
85
|
+
);
|
|
86
|
+
expect(statement.parameters).toEqual([
|
|
87
|
+
IncidentCreatedRenotify.hiddenFromStatusPagesMessage,
|
|
88
|
+
]);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
test("touches only InProgress rows of incidents that are not visible, counting NULL as hidden", async () => {
|
|
92
|
+
const statement: Statement = (await statementsFor("up"))[0]!;
|
|
93
|
+
|
|
94
|
+
expect(statement.sql).toContain(
|
|
95
|
+
`WHERE "subscriberNotificationStatusOnIncidentCreated" = '${StatusPageSubscriberNotificationStatus.InProgress}' AND "isVisibleOnStatusPage" IS NOT TRUE`,
|
|
96
|
+
);
|
|
97
|
+
// Nothing else narrows or widens it.
|
|
98
|
+
expect(statement.sql.split("WHERE")).toHaveLength(2);
|
|
99
|
+
expect(statement.sql).not.toMatch(/ OR /i);
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
test("migrated rows read exactly like rows the fixed worker skips", () => {
|
|
103
|
+
/*
|
|
104
|
+
* The migration keeps its own copy of the text so it never changes after
|
|
105
|
+
* it ships; the dashboard recognises the reason by this text.
|
|
106
|
+
*/
|
|
107
|
+
expect(HIDDEN_FROM_STATUS_PAGES_MESSAGE).toBe(
|
|
108
|
+
IncidentCreatedRenotify.hiddenFromStatusPagesMessage,
|
|
109
|
+
);
|
|
110
|
+
expect(
|
|
111
|
+
IncidentCreatedRenotify.isHiddenFromStatusPagesSkip({
|
|
112
|
+
status: StatusPageSubscriberNotificationStatus.Skipped,
|
|
113
|
+
message: HIDDEN_FROM_STATUS_PAGES_MESSAGE,
|
|
114
|
+
}),
|
|
115
|
+
).toBe(true);
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
test("names real Incident columns", () => {
|
|
119
|
+
expect(
|
|
120
|
+
incidentColumn("subscriberNotificationStatusOnIncidentCreated").options
|
|
121
|
+
.type,
|
|
122
|
+
).toBeDefined();
|
|
123
|
+
expect(
|
|
124
|
+
incidentColumn("subscriberNotificationStatusMessage").options.nullable,
|
|
125
|
+
).toBe(true);
|
|
126
|
+
// The worker reads a NULL visibility as hidden; the column allows it.
|
|
127
|
+
expect(incidentColumn("isVisibleOnStatusPage").options.nullable).toBe(true);
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
test("down() restores nothing", async () => {
|
|
131
|
+
expect(await statementsFor("down")).toEqual([]);
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
test("is registered exactly once, after the migrations before it, so it runs on boot", () => {
|
|
135
|
+
const registered: Array<new () => MigrationInterface> =
|
|
136
|
+
SchemaMigrations.filter(
|
|
137
|
+
(migration: new () => MigrationInterface): boolean => {
|
|
138
|
+
return (
|
|
139
|
+
migration === SkipHiddenIncidentCreatedNotifications1795300000000
|
|
140
|
+
);
|
|
141
|
+
},
|
|
142
|
+
);
|
|
143
|
+
|
|
144
|
+
expect(registered).toHaveLength(1);
|
|
145
|
+
expect(new SkipHiddenIncidentCreatedNotifications1795300000000().name).toBe(
|
|
146
|
+
"SkipHiddenIncidentCreatedNotifications1795300000000",
|
|
147
|
+
);
|
|
148
|
+
expect(
|
|
149
|
+
SchemaMigrations.indexOf(
|
|
150
|
+
SkipHiddenIncidentCreatedNotifications1795300000000,
|
|
151
|
+
),
|
|
152
|
+
).toBeGreaterThan(
|
|
153
|
+
SchemaMigrations.findIndex(
|
|
154
|
+
(migration: new () => MigrationInterface): boolean => {
|
|
155
|
+
return (
|
|
156
|
+
new migration().name === "AddUserProjectSsoConsent1795100000000"
|
|
157
|
+
);
|
|
158
|
+
},
|
|
159
|
+
),
|
|
160
|
+
);
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
/*
|
|
165
|
+
* Opt in with RUN_POSTGRES_HIDDEN_INCIDENT_NOTIFICATION_MIGRATION_TESTS=true
|
|
166
|
+
* and the normal database credentials (the Common test job does). The table
|
|
167
|
+
* is a minimal stand-in for Incident with the columns the migration reads and
|
|
168
|
+
* writes, typed as the entity declares them, in a uniquely named schema whose
|
|
169
|
+
* search_path excludes public - so no application row is ever touched.
|
|
170
|
+
*/
|
|
171
|
+
const describePostgres: typeof describe.skip =
|
|
172
|
+
process.env["RUN_POSTGRES_HIDDEN_INCIDENT_NOTIFICATION_MIGRATION_TESTS"] ===
|
|
173
|
+
"true"
|
|
174
|
+
? describe
|
|
175
|
+
: describe.skip;
|
|
176
|
+
|
|
177
|
+
interface StoredIncident {
|
|
178
|
+
_id: string;
|
|
179
|
+
isVisibleOnStatusPage: boolean | null;
|
|
180
|
+
status: string;
|
|
181
|
+
message: string | null;
|
|
182
|
+
postmortemStatus: string;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
describePostgres(
|
|
186
|
+
"SkipHiddenIncidentCreatedNotifications against Postgres",
|
|
187
|
+
() => {
|
|
188
|
+
const schema: string = `hidden_incident_notifications_${ObjectID.generate()
|
|
189
|
+
.toString()
|
|
190
|
+
.replace(/-/g, "")}`;
|
|
191
|
+
const migration: SkipHiddenIncidentCreatedNotifications1795300000000 =
|
|
192
|
+
new SkipHiddenIncidentCreatedNotifications1795300000000();
|
|
193
|
+
|
|
194
|
+
let database: DataSource;
|
|
195
|
+
let runner: QueryRunner;
|
|
196
|
+
|
|
197
|
+
async function insert(row: {
|
|
198
|
+
isVisibleOnStatusPage: boolean | null;
|
|
199
|
+
status: StatusPageSubscriberNotificationStatus;
|
|
200
|
+
message?: string | null;
|
|
201
|
+
}): Promise<string> {
|
|
202
|
+
const id: string = ObjectID.generate().toString();
|
|
203
|
+
await runner.query(
|
|
204
|
+
`INSERT INTO "Incident" ("_id", "isVisibleOnStatusPage", "subscriberNotificationStatusOnIncidentCreated", "subscriberNotificationStatusMessage") VALUES ($1, $2, $3, $4)`,
|
|
205
|
+
[id, row.isVisibleOnStatusPage, row.status, row.message ?? null],
|
|
206
|
+
);
|
|
207
|
+
return id;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
async function read(id: string): Promise<StoredIncident> {
|
|
211
|
+
const rows: Array<StoredIncident> = await runner.query(
|
|
212
|
+
`SELECT "_id", "isVisibleOnStatusPage", "subscriberNotificationStatusOnIncidentCreated" AS status, "subscriberNotificationStatusMessage" AS message, "subscriberNotificationStatusOnPostmortemPublished" AS "postmortemStatus" FROM "Incident" WHERE "_id" = $1`,
|
|
213
|
+
[id],
|
|
214
|
+
);
|
|
215
|
+
expect(rows).toHaveLength(1);
|
|
216
|
+
return rows[0]!;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
beforeAll(async () => {
|
|
220
|
+
database = new DataSource({
|
|
221
|
+
type: "postgres",
|
|
222
|
+
host:
|
|
223
|
+
process.env[
|
|
224
|
+
"HIDDEN_INCIDENT_NOTIFICATION_MIGRATION_TEST_DATABASE_HOST"
|
|
225
|
+
] || "localhost",
|
|
226
|
+
port: Number(
|
|
227
|
+
process.env[
|
|
228
|
+
"HIDDEN_INCIDENT_NOTIFICATION_MIGRATION_TEST_DATABASE_PORT"
|
|
229
|
+
] || "5400",
|
|
230
|
+
),
|
|
231
|
+
username: process.env["DATABASE_USERNAME"] || "postgres",
|
|
232
|
+
password: process.env["DATABASE_PASSWORD"] || "password",
|
|
233
|
+
database: process.env["DATABASE_NAME"] || "oneuptimedb",
|
|
234
|
+
entities: [],
|
|
235
|
+
schema,
|
|
236
|
+
synchronize: false,
|
|
237
|
+
extra: { options: `-c search_path=${schema}` },
|
|
238
|
+
});
|
|
239
|
+
await database.initialize();
|
|
240
|
+
await database.query(`CREATE SCHEMA "${schema}"`);
|
|
241
|
+
runner = database.createQueryRunner();
|
|
242
|
+
await runner.connect();
|
|
243
|
+
|
|
244
|
+
const currentSchema: Array<{ current_schema: string }> =
|
|
245
|
+
await runner.query("SELECT current_schema()");
|
|
246
|
+
expect(currentSchema[0]?.current_schema).toBe(schema);
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
beforeEach(async () => {
|
|
250
|
+
await runner.startTransaction();
|
|
251
|
+
// The columns as the migrated Incident table declares them.
|
|
252
|
+
await runner.query(
|
|
253
|
+
`CREATE TABLE "Incident" ("_id" uuid PRIMARY KEY, "isVisibleOnStatusPage" boolean DEFAULT true, "subscriberNotificationStatusOnIncidentCreated" character varying NOT NULL DEFAULT 'Pending', "subscriberNotificationStatusMessage" text, "subscriberNotificationStatusOnPostmortemPublished" character varying NOT NULL DEFAULT 'Pending')`,
|
|
254
|
+
);
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
afterEach(async () => {
|
|
258
|
+
if (runner?.isTransactionActive) {
|
|
259
|
+
await runner.rollbackTransaction();
|
|
260
|
+
}
|
|
261
|
+
});
|
|
262
|
+
|
|
263
|
+
afterAll(async () => {
|
|
264
|
+
if (runner) {
|
|
265
|
+
await runner.release();
|
|
266
|
+
}
|
|
267
|
+
if (database?.isInitialized) {
|
|
268
|
+
await database.query(`DROP SCHEMA IF EXISTS "${schema}" CASCADE`);
|
|
269
|
+
await database.destroy();
|
|
270
|
+
}
|
|
271
|
+
});
|
|
272
|
+
|
|
273
|
+
test("moves a hidden incident stuck InProgress to Skipped, with the reason", async () => {
|
|
274
|
+
const id: string = await insert({
|
|
275
|
+
isVisibleOnStatusPage: false,
|
|
276
|
+
status: StatusPageSubscriberNotificationStatus.InProgress,
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
await migration.up(runner);
|
|
280
|
+
|
|
281
|
+
expect(await read(id)).toEqual({
|
|
282
|
+
_id: id,
|
|
283
|
+
isVisibleOnStatusPage: false,
|
|
284
|
+
status: StatusPageSubscriberNotificationStatus.Skipped,
|
|
285
|
+
message: IncidentCreatedRenotify.hiddenFromStatusPagesMessage,
|
|
286
|
+
postmortemStatus: StatusPageSubscriberNotificationStatus.Pending,
|
|
287
|
+
});
|
|
288
|
+
});
|
|
289
|
+
|
|
290
|
+
test("treats a NULL visibility as hidden, as the worker did", async () => {
|
|
291
|
+
const id: string = await insert({
|
|
292
|
+
isVisibleOnStatusPage: null,
|
|
293
|
+
status: StatusPageSubscriberNotificationStatus.InProgress,
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
await migration.up(runner);
|
|
297
|
+
|
|
298
|
+
expect((await read(id)).status).toBe(
|
|
299
|
+
StatusPageSubscriberNotificationStatus.Skipped,
|
|
300
|
+
);
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
test("overwrites a stale message on the rows it settles", async () => {
|
|
304
|
+
const id: string = await insert({
|
|
305
|
+
isVisibleOnStatusPage: false,
|
|
306
|
+
status: StatusPageSubscriberNotificationStatus.InProgress,
|
|
307
|
+
message: "Notification queued for resending",
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
await migration.up(runner);
|
|
311
|
+
|
|
312
|
+
expect((await read(id)).message).toBe(
|
|
313
|
+
IncidentCreatedRenotify.hiddenFromStatusPagesMessage,
|
|
314
|
+
);
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
test("leaves a visible incident that is InProgress alone: it may be sending right now", async () => {
|
|
318
|
+
const id: string = await insert({
|
|
319
|
+
isVisibleOnStatusPage: true,
|
|
320
|
+
status: StatusPageSubscriberNotificationStatus.InProgress,
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
await migration.up(runner);
|
|
324
|
+
|
|
325
|
+
expect(await read(id)).toEqual(
|
|
326
|
+
expect.objectContaining({
|
|
327
|
+
status: StatusPageSubscriberNotificationStatus.InProgress,
|
|
328
|
+
message: null,
|
|
329
|
+
}),
|
|
330
|
+
);
|
|
331
|
+
});
|
|
332
|
+
|
|
333
|
+
test.each([
|
|
334
|
+
StatusPageSubscriberNotificationStatus.Pending,
|
|
335
|
+
StatusPageSubscriberNotificationStatus.Success,
|
|
336
|
+
StatusPageSubscriberNotificationStatus.Failed,
|
|
337
|
+
StatusPageSubscriberNotificationStatus.Skipped,
|
|
338
|
+
])(
|
|
339
|
+
"leaves a hidden incident whose notification is %s alone",
|
|
340
|
+
async (status: StatusPageSubscriberNotificationStatus) => {
|
|
341
|
+
const id: string = await insert({
|
|
342
|
+
isVisibleOnStatusPage: false,
|
|
343
|
+
status,
|
|
344
|
+
message: "original message",
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
await migration.up(runner);
|
|
348
|
+
|
|
349
|
+
expect(await read(id)).toEqual(
|
|
350
|
+
expect.objectContaining({ status, message: "original message" }),
|
|
351
|
+
);
|
|
352
|
+
},
|
|
353
|
+
);
|
|
354
|
+
|
|
355
|
+
test("settles every stuck row in one pass and nothing else", async () => {
|
|
356
|
+
const stuck: Array<string> = [];
|
|
357
|
+
for (let i: number = 0; i < 5; i++) {
|
|
358
|
+
stuck.push(
|
|
359
|
+
await insert({
|
|
360
|
+
isVisibleOnStatusPage: false,
|
|
361
|
+
status: StatusPageSubscriberNotificationStatus.InProgress,
|
|
362
|
+
}),
|
|
363
|
+
);
|
|
364
|
+
}
|
|
365
|
+
const untouched: string = await insert({
|
|
366
|
+
isVisibleOnStatusPage: true,
|
|
367
|
+
status: StatusPageSubscriberNotificationStatus.Success,
|
|
368
|
+
});
|
|
369
|
+
|
|
370
|
+
await migration.up(runner);
|
|
371
|
+
|
|
372
|
+
for (const id of stuck) {
|
|
373
|
+
expect((await read(id)).status).toBe(
|
|
374
|
+
StatusPageSubscriberNotificationStatus.Skipped,
|
|
375
|
+
);
|
|
376
|
+
}
|
|
377
|
+
expect((await read(untouched)).status).toBe(
|
|
378
|
+
StatusPageSubscriberNotificationStatus.Success,
|
|
379
|
+
);
|
|
380
|
+
});
|
|
381
|
+
|
|
382
|
+
test("is safe to run twice", async () => {
|
|
383
|
+
const id: string = await insert({
|
|
384
|
+
isVisibleOnStatusPage: false,
|
|
385
|
+
status: StatusPageSubscriberNotificationStatus.InProgress,
|
|
386
|
+
});
|
|
387
|
+
|
|
388
|
+
await migration.up(runner);
|
|
389
|
+
await migration.up(runner);
|
|
390
|
+
|
|
391
|
+
expect((await read(id)).status).toBe(
|
|
392
|
+
StatusPageSubscriberNotificationStatus.Skipped,
|
|
393
|
+
);
|
|
394
|
+
});
|
|
395
|
+
|
|
396
|
+
test("down() leaves the settled rows as they are", async () => {
|
|
397
|
+
const id: string = await insert({
|
|
398
|
+
isVisibleOnStatusPage: false,
|
|
399
|
+
status: StatusPageSubscriberNotificationStatus.InProgress,
|
|
400
|
+
});
|
|
401
|
+
|
|
402
|
+
await migration.up(runner);
|
|
403
|
+
await migration.down(runner);
|
|
404
|
+
|
|
405
|
+
expect((await read(id)).status).toBe(
|
|
406
|
+
StatusPageSubscriberNotificationStatus.Skipped,
|
|
407
|
+
);
|
|
408
|
+
});
|
|
409
|
+
},
|
|
410
|
+
);
|