@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
|
@@ -34,6 +34,7 @@ import AIIncidentPostmortemRunner from "../Utils/AI/SRE/IncidentPostmortemRunner
|
|
|
34
34
|
import InvestigationGrader from "../Utils/AI/SRE/InvestigationGrader";
|
|
35
35
|
import { IncidentFeedEventType } from "../../Models/DatabaseModels/IncidentFeed";
|
|
36
36
|
import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
|
|
37
|
+
import SubscriberNotificationResendAccess from "../Utils/StatusPage/SubscriberNotificationResendAccess";
|
|
37
38
|
import { LIMIT_PER_PROJECT } from "../../Types/Database/LimitMax";
|
|
38
39
|
import WorkspaceNotificationRuleService from "./WorkspaceNotificationRuleService";
|
|
39
40
|
import Semaphore, { SemaphoreMutex } from "../Infrastructure/Semaphore";
|
|
@@ -748,6 +749,18 @@ ${createdItem.rootCause}`,
|
|
|
748
749
|
protected override async onBeforeUpdate(
|
|
749
750
|
updateBy: UpdateBy<IncidentStateTimeline>,
|
|
750
751
|
): Promise<OnUpdate<IncidentStateTimeline>> {
|
|
752
|
+
/*
|
|
753
|
+
* Retry - a user's Pending - over a state change notification that is
|
|
754
|
+
* being sent would let a second run send it alongside, or be overwritten
|
|
755
|
+
* when the send settles (SubscriberNotificationResendAccess).
|
|
756
|
+
*/
|
|
757
|
+
await SubscriberNotificationResendAccess.assertNotQueuedWhileBeingSent({
|
|
758
|
+
modelType: IncidentStateTimeline,
|
|
759
|
+
service: this,
|
|
760
|
+
updateBy: updateBy,
|
|
761
|
+
statusColumns: ["subscriberNotificationStatus"],
|
|
762
|
+
});
|
|
763
|
+
|
|
751
764
|
const incidentIds: Array<ObjectID> =
|
|
752
765
|
await this.getIncidentIdsForTimelineQuery(updateBy);
|
|
753
766
|
|
|
@@ -10,6 +10,7 @@ import LabelService from "./LabelService";
|
|
|
10
10
|
import MonitorService from "./MonitorService";
|
|
11
11
|
import MonitorStatusService from "./MonitorStatusService";
|
|
12
12
|
import OnCallDutyPolicyService from "./OnCallDutyPolicyService";
|
|
13
|
+
import StatusPageService from "./StatusPageService";
|
|
13
14
|
import DatabaseCommonInteractionProps from "../../Types/BaseDatabase/DatabaseCommonInteractionProps";
|
|
14
15
|
import LIMIT_MAX from "../../Types/Database/LimitMax";
|
|
15
16
|
import Dictionary from "../../Types/Dictionary";
|
|
@@ -28,6 +29,8 @@ import Query from "../Types/Database/Query";
|
|
|
28
29
|
import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
|
|
29
30
|
import OwnerRuleAssignment from "../Utils/Rules/OwnerRuleAssignment";
|
|
30
31
|
import QueryDeepPartialEntity from "../../Types/Database/PartialEntity";
|
|
32
|
+
import StatusPageReadAccess from "../Utils/StatusPage/StatusPageReadAccess";
|
|
33
|
+
import IncidentScopeAddedPagesNotification from "../../Types/StatusPage/IncidentScopeAddedPagesNotification";
|
|
31
34
|
|
|
32
35
|
export class Service extends DatabaseService<Model> {
|
|
33
36
|
public constructor() {
|
|
@@ -52,6 +55,12 @@ export class Service extends DatabaseService<Model> {
|
|
|
52
55
|
const projectId: ObjectID | undefined =
|
|
53
56
|
createBy.props.tenantId || createBy.data.projectId;
|
|
54
57
|
|
|
58
|
+
// Derived from the list, whatever the caller sent (see the column).
|
|
59
|
+
createBy.data.isScopedToStatusPages =
|
|
60
|
+
IncidentScopeAddedPagesNotification.normalizeStatusPageIds(
|
|
61
|
+
createBy.data.statusPages,
|
|
62
|
+
).length > 0;
|
|
63
|
+
|
|
55
64
|
await ProjectScopedReferenceValidator.validateReferencesBelongToProject({
|
|
56
65
|
projectId: projectId,
|
|
57
66
|
subject: "incident template",
|
|
@@ -64,6 +73,19 @@ export class Service extends DatabaseService<Model> {
|
|
|
64
73
|
],
|
|
65
74
|
});
|
|
66
75
|
|
|
76
|
+
/*
|
|
77
|
+
* A template's status pages are picked for everyone who declares from
|
|
78
|
+
* it, so picking them needs the same read access as picking an
|
|
79
|
+
* incident's (see StatusPageReadAccess).
|
|
80
|
+
*/
|
|
81
|
+
await StatusPageReadAccess.assertCallerCanPickStatusPages({
|
|
82
|
+
statusPageIds: IncidentScopeAddedPagesNotification.normalizeStatusPageIds(
|
|
83
|
+
createBy.data.statusPages,
|
|
84
|
+
),
|
|
85
|
+
props: createBy.props,
|
|
86
|
+
subject: "incident template",
|
|
87
|
+
});
|
|
88
|
+
|
|
67
89
|
return { createBy, carryForward: null };
|
|
68
90
|
}
|
|
69
91
|
|
|
@@ -71,6 +93,22 @@ export class Service extends DatabaseService<Model> {
|
|
|
71
93
|
protected override async onBeforeUpdate(
|
|
72
94
|
updateBy: UpdateBy<Model>,
|
|
73
95
|
): Promise<OnUpdate<Model>> {
|
|
96
|
+
/*
|
|
97
|
+
* The scope flag follows a write to the list and nothing else: a client
|
|
98
|
+
* value is dropped, and deleting the template's pages (join rows
|
|
99
|
+
* cascading away) never clears it.
|
|
100
|
+
*/
|
|
101
|
+
const data: Dictionary<unknown> = updateBy.data as Dictionary<unknown>;
|
|
102
|
+
|
|
103
|
+
delete data["isScopedToStatusPages"];
|
|
104
|
+
|
|
105
|
+
if (data["statusPages"] !== undefined) {
|
|
106
|
+
data["isScopedToStatusPages"] =
|
|
107
|
+
IncidentScopeAddedPagesNotification.normalizeStatusPageIds(
|
|
108
|
+
data["statusPages"],
|
|
109
|
+
).length > 0;
|
|
110
|
+
}
|
|
111
|
+
|
|
74
112
|
const references: Array<ProjectScopedReference> =
|
|
75
113
|
this.getProjectScopedReferences(updateBy.data);
|
|
76
114
|
|
|
@@ -131,9 +169,75 @@ export class Service extends DatabaseService<Model> {
|
|
|
131
169
|
});
|
|
132
170
|
}
|
|
133
171
|
|
|
172
|
+
// Once the pages are known to be the project's.
|
|
173
|
+
await this.assertCallerCanReadAddedStatusPages(updateBy);
|
|
174
|
+
|
|
134
175
|
return { updateBy, carryForward: null };
|
|
135
176
|
}
|
|
136
177
|
|
|
178
|
+
/*
|
|
179
|
+
* The status pages an update adds to a template must be pages the caller
|
|
180
|
+
* can read (see StatusPageReadAccess). Pages the template already holds are
|
|
181
|
+
* not checked, so saving a template limited to a page the editor cannot
|
|
182
|
+
* see does not fail. The templates are read as root, limited to the
|
|
183
|
+
* caller's project: the update's own tenant filter is only added after
|
|
184
|
+
* this hook.
|
|
185
|
+
*/
|
|
186
|
+
private async assertCallerCanReadAddedStatusPages(
|
|
187
|
+
updateBy: UpdateBy<Model>,
|
|
188
|
+
): Promise<void> {
|
|
189
|
+
const requested: unknown = (updateBy.data as Dictionary<unknown>)[
|
|
190
|
+
"statusPages"
|
|
191
|
+
];
|
|
192
|
+
|
|
193
|
+
if (updateBy.props.isRoot || requested === undefined) {
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
const requestedIds: Array<string> =
|
|
198
|
+
IncidentScopeAddedPagesNotification.normalizeStatusPageIds(requested);
|
|
199
|
+
|
|
200
|
+
if (requestedIds.length === 0) {
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
const templates: Array<Model> = await this.findBy({
|
|
205
|
+
query: updateBy.props.tenantId
|
|
206
|
+
? { ...updateBy.query, projectId: updateBy.props.tenantId }
|
|
207
|
+
: updateBy.query,
|
|
208
|
+
select: {
|
|
209
|
+
_id: true,
|
|
210
|
+
statusPages: {
|
|
211
|
+
_id: true,
|
|
212
|
+
},
|
|
213
|
+
},
|
|
214
|
+
limit: LIMIT_MAX,
|
|
215
|
+
skip: 0,
|
|
216
|
+
props: {
|
|
217
|
+
isRoot: true,
|
|
218
|
+
},
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
const addedIds: Array<string> = [];
|
|
222
|
+
|
|
223
|
+
for (const template of templates) {
|
|
224
|
+
for (const id of IncidentScopeAddedPagesNotification.getScopeChange({
|
|
225
|
+
before: template.statusPages,
|
|
226
|
+
after: requestedIds,
|
|
227
|
+
}).addedStatusPageIds) {
|
|
228
|
+
if (!addedIds.includes(id)) {
|
|
229
|
+
addedIds.push(id);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
await StatusPageReadAccess.assertCallerCanPickStatusPages({
|
|
235
|
+
statusPageIds: addedIds,
|
|
236
|
+
props: updateBy.props,
|
|
237
|
+
subject: "incident template",
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
|
|
137
241
|
/*
|
|
138
242
|
* The many-to-many lists whose ids must belong to the template's project.
|
|
139
243
|
* Built per call rather than at module load: these services sit in an
|
|
@@ -157,6 +261,11 @@ export class Service extends DatabaseService<Model> {
|
|
|
157
261
|
modelName: "On-Call Policy",
|
|
158
262
|
service: OnCallDutyPolicyService,
|
|
159
263
|
},
|
|
264
|
+
{
|
|
265
|
+
column: "statusPages",
|
|
266
|
+
modelName: "Status Page",
|
|
267
|
+
service: StatusPageService,
|
|
268
|
+
},
|
|
160
269
|
...getAffectedResourceRelations(this.getModel()),
|
|
161
270
|
];
|
|
162
271
|
}
|
|
@@ -10,6 +10,8 @@ import ColumnLength from "../../Types/Database/ColumnLength";
|
|
|
10
10
|
import QueryDeepPartialEntity from "../../Types/Database/PartialEntity";
|
|
11
11
|
import CreateBy from "../Types/Database/CreateBy";
|
|
12
12
|
import { OnCreate } from "../Types/Database/Hooks";
|
|
13
|
+
import { AggregateRow } from "../Types/Database/AggregateBy";
|
|
14
|
+
import DatabaseCommonInteractionProps from "../../Types/BaseDatabase/DatabaseCommonInteractionProps";
|
|
13
15
|
import BadDataException from "../../Types/Exception/BadDataException";
|
|
14
16
|
import Dictionary from "../../Types/Dictionary";
|
|
15
17
|
import { JSONObject } from "../../Types/JSON";
|
|
@@ -22,6 +24,12 @@ import {
|
|
|
22
24
|
MANUAL_ENTITY_IDENTITY_ATTRIBUTE,
|
|
23
25
|
} from "../../Utils/Telemetry/EntityKey";
|
|
24
26
|
import logger from "../Utils/Logger";
|
|
27
|
+
import {
|
|
28
|
+
INVENTORY_OVERVIEW_GROUP_BY,
|
|
29
|
+
INVENTORY_OVERVIEW_SELECT,
|
|
30
|
+
InventoryOverviewCounts,
|
|
31
|
+
readInventoryOverviewGroups,
|
|
32
|
+
} from "../Utils/Inventory/InventoryOverviewAggregation";
|
|
25
33
|
import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
|
|
26
34
|
import { ExtractedEntity } from "../Utils/Telemetry/TelemetryEntity";
|
|
27
35
|
import {
|
|
@@ -147,6 +155,36 @@ export class InventoryItemService extends DatabaseService<Model> {
|
|
|
147
155
|
return { createBy, carryForward: null };
|
|
148
156
|
}
|
|
149
157
|
|
|
158
|
+
/**
|
|
159
|
+
* The Inventory Overview's tiles and per-type breakdown, counted over the
|
|
160
|
+
* project's whole unarchived estate. See INVENTORY_OVERVIEW_SELECT.
|
|
161
|
+
*
|
|
162
|
+
* Archived rows are excluded because every tile drills into the live Items
|
|
163
|
+
* list, which excludes them too.
|
|
164
|
+
*
|
|
165
|
+
* The GROUP BY carries no limit: capping it would cap the totals summed
|
|
166
|
+
* from it. The number of groups is bounded by the entity-type vocabulary —
|
|
167
|
+
* ingest maps to a fixed set of types, manual creates are confined to
|
|
168
|
+
* MANUAL_ENTITY_TYPES, and the column is not updatable.
|
|
169
|
+
*/
|
|
170
|
+
@CaptureSpan()
|
|
171
|
+
public async getOverviewCounts(data: {
|
|
172
|
+
projectId: ObjectID;
|
|
173
|
+
props: DatabaseCommonInteractionProps;
|
|
174
|
+
}): Promise<InventoryOverviewCounts> {
|
|
175
|
+
const rows: Array<AggregateRow> = await this.aggregateBy({
|
|
176
|
+
query: {
|
|
177
|
+
projectId: data.projectId,
|
|
178
|
+
isArchived: false,
|
|
179
|
+
},
|
|
180
|
+
groupBy: INVENTORY_OVERVIEW_GROUP_BY,
|
|
181
|
+
select: INVENTORY_OVERVIEW_SELECT,
|
|
182
|
+
props: data.props,
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
return readInventoryOverviewGroups(rows);
|
|
186
|
+
}
|
|
187
|
+
|
|
150
188
|
/**
|
|
151
189
|
* Forward-only registry reconciliation: upsert a catalog row per
|
|
152
190
|
* discovered entity, bump `lastSeenAt`, merge descriptive attributes
|
|
@@ -204,14 +204,23 @@ export class Service extends DatabaseService<Model> {
|
|
|
204
204
|
return cached;
|
|
205
205
|
}
|
|
206
206
|
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
207
|
+
/*
|
|
208
|
+
* Validated rather than caught. ObjectID's constructor stores whatever
|
|
209
|
+
* string it is handed and never throws, so the try/catch this replaced
|
|
210
|
+
* caught nothing: a malformed id reached Postgres as an invalid uuid
|
|
211
|
+
* literal, which errors on every attempt AND skipped the negative cache
|
|
212
|
+
* below, because the row was never absent - the query failed. credentialId
|
|
213
|
+
* is an MQTT username, so it is attacker-controlled, and that made the
|
|
214
|
+
* negative cache bypassable with random garbage. Same guard, and the same
|
|
215
|
+
* reason for it, as ProjectAuthorization's API-key check.
|
|
216
|
+
*/
|
|
217
|
+
if (!ObjectID.isValidUUID(credentialId)) {
|
|
211
218
|
this.contextCache.set(credentialId, null, NEGATIVE_TTL_MS);
|
|
212
219
|
return null;
|
|
213
220
|
}
|
|
214
221
|
|
|
222
|
+
const idObject: ObjectID = new ObjectID(credentialId);
|
|
223
|
+
|
|
215
224
|
const credential: Model | null = await this.findOneBy({
|
|
216
225
|
query: { _id: idObject },
|
|
217
226
|
select: {
|
|
@@ -19,6 +19,7 @@ import Query from "../Types/Database/Query";
|
|
|
19
19
|
import File from "../../Models/DatabaseModels/File";
|
|
20
20
|
import FileAttachmentMarkdownUtil from "../Utils/FileAttachmentMarkdownUtil";
|
|
21
21
|
import { syncIsPublicForMarkdownImages } from "../Utils/InlineImageAccessTokenSync";
|
|
22
|
+
import SubscriberNotificationResendAccess from "../Utils/StatusPage/SubscriberNotificationResendAccess";
|
|
22
23
|
|
|
23
24
|
export class Service extends DatabaseService<Model> {
|
|
24
25
|
public constructor() {
|
|
@@ -122,11 +123,24 @@ export class Service extends DatabaseService<Model> {
|
|
|
122
123
|
* An edit tells subscribers nothing unless the editor asked for it on this
|
|
123
124
|
* edit (see SubscriberUpdateNotification). When they did, queue the update
|
|
124
125
|
* notification; the ScheduledMaintenancePublicNote worker job sends it.
|
|
126
|
+
*
|
|
127
|
+
* Sending the note's 'posted' notification again - its status written back
|
|
128
|
+
* to Pending, as the dashboard's Retry does - needs the permission to post
|
|
129
|
+
* a note that notifies subscribers, and a note whose notification can go
|
|
130
|
+
* out again (see SubscriberNotificationResendAccess). So does telling
|
|
131
|
+
* subscribers about an edit, which is also refused while that update
|
|
132
|
+
* notification is being sent.
|
|
125
133
|
*/
|
|
126
134
|
@CaptureSpan()
|
|
127
135
|
protected override async onBeforeUpdate(
|
|
128
136
|
updateBy: UpdateBy<Model>,
|
|
129
137
|
): Promise<OnUpdate<Model>> {
|
|
138
|
+
await SubscriberNotificationResendAccess.assertPublicNoteResendAllowed({
|
|
139
|
+
modelType: Model,
|
|
140
|
+
service: this,
|
|
141
|
+
updateBy: updateBy,
|
|
142
|
+
});
|
|
143
|
+
|
|
130
144
|
if (SubscriberUpdateNotification.isRequested(updateBy.miscDataProps)) {
|
|
131
145
|
updateBy.data.subscriberNotificationStatusOnNoteUpdated =
|
|
132
146
|
StatusPageSubscriberNotificationStatus.Pending;
|
|
@@ -134,6 +148,20 @@ export class Service extends DatabaseService<Model> {
|
|
|
134
148
|
SubscriberUpdateNotification.queuedMessage;
|
|
135
149
|
}
|
|
136
150
|
|
|
151
|
+
/*
|
|
152
|
+
* Telling subscribers about the edit - asked for above, or written as
|
|
153
|
+
* Pending directly (the dashboard's Retry of a failed update) - needs
|
|
154
|
+
* the permission to post a note that notifies subscribers too, and is
|
|
155
|
+
* refused while the update notification is being sent.
|
|
156
|
+
*/
|
|
157
|
+
await SubscriberNotificationResendAccess.assertPublicNoteUpdateNotificationAllowed(
|
|
158
|
+
{
|
|
159
|
+
modelType: Model,
|
|
160
|
+
service: this,
|
|
161
|
+
updateBy: updateBy,
|
|
162
|
+
},
|
|
163
|
+
);
|
|
164
|
+
|
|
137
165
|
return {
|
|
138
166
|
updateBy: updateBy,
|
|
139
167
|
carryForward: null,
|
|
@@ -246,8 +274,9 @@ ${(createdItem.note || "") + attachmentsMarkdown}
|
|
|
246
274
|
{
|
|
247
275
|
scheduledMaintenanceId: updatedItem.scheduledMaintenanceId!,
|
|
248
276
|
projectId: updatedItem.projectId!,
|
|
277
|
+
// An edit to a public note is a public note event, not a private one.
|
|
249
278
|
scheduledMaintenanceFeedEventType:
|
|
250
|
-
ScheduledMaintenanceFeedEventType.
|
|
279
|
+
ScheduledMaintenanceFeedEventType.PublicNote,
|
|
251
280
|
displayColor: Blue500,
|
|
252
281
|
userId: userId || undefined,
|
|
253
282
|
|
|
@@ -9,6 +9,10 @@ import DatabaseService from "./DatabaseService";
|
|
|
9
9
|
import ScheduledMaintenanceCustomField from "../../Models/DatabaseModels/ScheduledMaintenanceCustomField";
|
|
10
10
|
import CustomFieldMappingService from "./CustomFieldMappingService";
|
|
11
11
|
import MonitorService from "./MonitorService";
|
|
12
|
+
import LinkedAffectedResources, {
|
|
13
|
+
LinkedAffectedResource,
|
|
14
|
+
LinkedAffectedResourceRelation,
|
|
15
|
+
} from "../Utils/AffectedResources/LinkedAffectedResources";
|
|
12
16
|
import ScheduledMaintenanceOwnerTeamService from "./ScheduledMaintenanceOwnerTeamService";
|
|
13
17
|
import ScheduledMaintenanceOwnerUserService from "./ScheduledMaintenanceOwnerUserService";
|
|
14
18
|
import ScheduledMaintenanceStateService from "./ScheduledMaintenanceStateService";
|
|
@@ -56,6 +60,7 @@ import SmsService from "../../Server/Services/SmsService";
|
|
|
56
60
|
import StatusPageResourceService from "../../Server/Services/StatusPageResourceService";
|
|
57
61
|
import StatusPageService from "../../Server/Services/StatusPageService";
|
|
58
62
|
import StatusPageSubscriberService from "../../Server/Services/StatusPageSubscriberService";
|
|
63
|
+
import StatusPageSubscriberUnsubscribe from "../../Types/StatusPage/StatusPageSubscriberUnsubscribe";
|
|
59
64
|
import QueryHelper from "../../Server/Types/Database/QueryHelper";
|
|
60
65
|
import Markdown, { MarkdownContentType } from "../../Server/Types/Markdown";
|
|
61
66
|
import logger, { LogAttributes } from "../../Server/Utils/Logger";
|
|
@@ -86,6 +91,8 @@ import ProjectService from "./ProjectService";
|
|
|
86
91
|
import StatusPageSubscriberNotificationTemplateService, {
|
|
87
92
|
Service as StatusPageSubscriberNotificationTemplateServiceClass,
|
|
88
93
|
} from "./StatusPageSubscriberNotificationTemplateService";
|
|
94
|
+
import StatusPageResourceUtil from "../Utils/StatusPageResource";
|
|
95
|
+
import SafeHtml from "../../Types/SafeHtml";
|
|
89
96
|
import StatusPageSubscriberNotificationTemplate from "../../Models/DatabaseModels/StatusPageSubscriberNotificationTemplate";
|
|
90
97
|
import StatusPageSubscriberNotificationEventType from "../../Types/StatusPage/StatusPageSubscriberNotificationEventType";
|
|
91
98
|
import StatusPageSubscriberNotificationMethod from "../../Types/StatusPage/StatusPageSubscriberNotificationMethod";
|
|
@@ -204,12 +211,20 @@ export class Service extends DatabaseService<Model> {
|
|
|
204
211
|
|
|
205
212
|
// Send email to Email subscribers.
|
|
206
213
|
|
|
214
|
+
/*
|
|
215
|
+
* The resources are read without their groups, so both forms are the
|
|
216
|
+
* names joined by commas. The HTML one, for email bodies, has every
|
|
217
|
+
* name escaped; SMS, Slack, subjects and webhooks get the names as
|
|
218
|
+
* written.
|
|
219
|
+
*/
|
|
207
220
|
const resourcesAffected: string =
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
221
|
+
StatusPageResourceUtil.getResourcesGroupedByGroupNameAsPlainText(
|
|
222
|
+
statusPageToResources[statuspage._id!] || [],
|
|
223
|
+
);
|
|
224
|
+
const resourcesAffectedHtml: string =
|
|
225
|
+
StatusPageResourceUtil.getResourcesGroupedByGroupName(
|
|
226
|
+
statusPageToResources[statuspage._id!] || [],
|
|
227
|
+
);
|
|
213
228
|
|
|
214
229
|
// Fetch custom templates for each notification method
|
|
215
230
|
const [
|
|
@@ -266,7 +281,7 @@ export class Service extends DatabaseService<Model> {
|
|
|
266
281
|
const unsubscribeUrl: string =
|
|
267
282
|
StatusPageSubscriberService.getUnsubscribeLink(
|
|
268
283
|
URL.fromString(statusPageURL),
|
|
269
|
-
subscriber
|
|
284
|
+
subscriber,
|
|
270
285
|
).toString();
|
|
271
286
|
|
|
272
287
|
// Template variables for custom templates, as Markdown (Slack)
|
|
@@ -294,6 +309,19 @@ export class Service extends DatabaseService<Model> {
|
|
|
294
309
|
};
|
|
295
310
|
|
|
296
311
|
if (subscriber.subscriberPhone) {
|
|
312
|
+
/*
|
|
313
|
+
* On a public status page the SMS keeps the shorter manage link,
|
|
314
|
+
* which works there without signing in: an SMS is billed by the
|
|
315
|
+
* segment (see StatusPageSubscriberUnsubscribe.buildSmsLink).
|
|
316
|
+
*/
|
|
317
|
+
const smsUnsubscribeUrl: string =
|
|
318
|
+
StatusPageSubscriberUnsubscribe.buildSmsLink({
|
|
319
|
+
isPublicStatusPage: statuspage.isPublicStatusPage,
|
|
320
|
+
statusPageUrl: statusPageURL,
|
|
321
|
+
subscriberId: subscriber.id!,
|
|
322
|
+
unsubscribeUrl: unsubscribeUrl,
|
|
323
|
+
});
|
|
324
|
+
|
|
297
325
|
let smsMessage: string;
|
|
298
326
|
|
|
299
327
|
if (
|
|
@@ -305,11 +333,14 @@ export class Service extends DatabaseService<Model> {
|
|
|
305
333
|
smsMessage =
|
|
306
334
|
StatusPageSubscriberNotificationTemplateServiceClass.compileTemplate(
|
|
307
335
|
smsTemplate.templateBody,
|
|
308
|
-
|
|
336
|
+
{
|
|
337
|
+
...plainTextTemplateVariables,
|
|
338
|
+
unsubscribeUrl: smsUnsubscribeUrl,
|
|
339
|
+
},
|
|
309
340
|
);
|
|
310
341
|
} else {
|
|
311
342
|
// Use default template
|
|
312
|
-
smsMessage = `Scheduled Maintenance: ${event.title || ""} on ${statusPageName}.${resourcesAffected ? ` Impact: ${resourcesAffected}.` : ""} Details: ${scheduledEventDetailsUrl}. Unsub: ${
|
|
343
|
+
smsMessage = `Scheduled Maintenance: ${event.title || ""} on ${statusPageName}.${resourcesAffected ? ` Impact: ${resourcesAffected}.` : ""} Details: ${scheduledEventDetailsUrl}. Unsub: ${smsUnsubscribeUrl}`;
|
|
313
344
|
}
|
|
314
345
|
|
|
315
346
|
const sms: SMS = {
|
|
@@ -404,7 +435,20 @@ ${resourcesAffected ? `**Resources Affected:** ${resourcesAffected}` : ""}
|
|
|
404
435
|
const statusPageIdString: string | null =
|
|
405
436
|
statuspage.id?.toString() || statuspage._id?.toString() || null;
|
|
406
437
|
|
|
407
|
-
|
|
438
|
+
const scheduledAtHtml: string =
|
|
439
|
+
OneUptimeDate.getDateAsFormattedHTMLInMultipleTimezones({
|
|
440
|
+
date: event.startsAt!,
|
|
441
|
+
timezones: statuspage.subscriberTimezones || [],
|
|
442
|
+
use12HourFormat: true,
|
|
443
|
+
});
|
|
444
|
+
|
|
445
|
+
/*
|
|
446
|
+
* The default template's variables. resourcesAffected,
|
|
447
|
+
* scheduledAt and eventDescription are HTML (the template puts
|
|
448
|
+
* them in its raw-HTML slot); the footer is HTML the status
|
|
449
|
+
* page's admins wrote, as they write the template. Everything
|
|
450
|
+
* else is plain text, which the template escapes.
|
|
451
|
+
*/
|
|
408
452
|
const emailVars: Record<string, string> = {
|
|
409
453
|
statusPageName: statusPageName,
|
|
410
454
|
statusPageUrl: statusPageURL,
|
|
@@ -421,13 +465,8 @@ ${resourcesAffected ? `**Resources Affected:** ${resourcesAffected}` : ""}
|
|
|
421
465
|
: "false",
|
|
422
466
|
subscriberEmailNotificationFooterText:
|
|
423
467
|
statuspage.subscriberEmailNotificationFooterText || "",
|
|
424
|
-
resourcesAffected:
|
|
425
|
-
scheduledAt:
|
|
426
|
-
OneUptimeDate.getDateAsFormattedHTMLInMultipleTimezones({
|
|
427
|
-
date: event.startsAt!,
|
|
428
|
-
timezones: statuspage.subscriberTimezones || [],
|
|
429
|
-
use12HourFormat: true,
|
|
430
|
-
}),
|
|
468
|
+
resourcesAffected: resourcesAffectedHtml,
|
|
469
|
+
scheduledAt: scheduledAtHtml,
|
|
431
470
|
eventTitle: event.title || "",
|
|
432
471
|
eventDescription: eventDescriptionHtml,
|
|
433
472
|
unsubscribeUrl: unsubscribeUrl,
|
|
@@ -444,14 +483,29 @@ ${resourcesAffected ? `**Resources Affected:** ${resourcesAffected}` : ""}
|
|
|
444
483
|
* is configured. The body is HTML, so the description is too.
|
|
445
484
|
* The subject is plain text, including the email-only
|
|
446
485
|
* variables that are HTML in the body.
|
|
486
|
+
*
|
|
487
|
+
* In the body, the plain values are escaped
|
|
488
|
+
* (compileEmailBodyTemplate) and only the ones wrapped in
|
|
489
|
+
* SafeHtml below go in as HTML.
|
|
447
490
|
*/
|
|
448
491
|
const customEmailBody: string =
|
|
449
|
-
StatusPageSubscriberNotificationTemplateServiceClass.
|
|
492
|
+
StatusPageSubscriberNotificationTemplateServiceClass.compileEmailBodyTemplate(
|
|
450
493
|
emailTemplate.templateBody,
|
|
451
494
|
{
|
|
452
495
|
...templateVariables,
|
|
453
496
|
...emailVars,
|
|
454
|
-
|
|
497
|
+
resourcesAffected: SafeHtml.fromTrustedHtml(
|
|
498
|
+
resourcesAffectedHtml,
|
|
499
|
+
),
|
|
500
|
+
scheduledAt: SafeHtml.fromTrustedHtml(scheduledAtHtml),
|
|
501
|
+
eventDescription:
|
|
502
|
+
SafeHtml.fromTrustedHtml(eventDescriptionHtml),
|
|
503
|
+
scheduledMaintenanceDescription:
|
|
504
|
+
SafeHtml.fromTrustedHtml(eventDescriptionHtml),
|
|
505
|
+
subscriberEmailNotificationFooterText:
|
|
506
|
+
SafeHtml.fromTrustedHtml(
|
|
507
|
+
emailVars["subscriberEmailNotificationFooterText"],
|
|
508
|
+
),
|
|
455
509
|
},
|
|
456
510
|
);
|
|
457
511
|
const customEmailSubject: string = emailTemplate.emailSubject
|
|
@@ -1180,10 +1234,6 @@ ${resourcesAffected ? `**Resources Affected:** ${resourcesAffected}` : ""}
|
|
|
1180
1234
|
},
|
|
1181
1235
|
startsAt: true,
|
|
1182
1236
|
endsAt: true,
|
|
1183
|
-
monitors: {
|
|
1184
|
-
name: true,
|
|
1185
|
-
_id: true,
|
|
1186
|
-
},
|
|
1187
1237
|
labels: {
|
|
1188
1238
|
name: true,
|
|
1189
1239
|
},
|
|
@@ -1448,14 +1498,23 @@ ${scheduledMaintenance.description || "No description provided."}
|
|
|
1448
1498
|
feedInfoInMarkdown += `⏳ **Scheduled Maintenance State**: ${scheduledMaintenance.currentScheduledMaintenanceState.name} \n\n`;
|
|
1449
1499
|
}
|
|
1450
1500
|
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1501
|
+
// Everything the event's Affected Resources card lists, monitors first.
|
|
1502
|
+
const resources: Array<LinkedAffectedResource> =
|
|
1503
|
+
await LinkedAffectedResources.readForScheduledMaintenance({
|
|
1504
|
+
service: this,
|
|
1505
|
+
projectId: scheduledMaintenance.projectId!,
|
|
1506
|
+
scheduledMaintenanceId: scheduledMaintenance.id!,
|
|
1507
|
+
});
|
|
1508
|
+
|
|
1509
|
+
if (resources.length > 0) {
|
|
1455
1510
|
feedInfoInMarkdown += `🌎 **Resources Affected**:\n`;
|
|
1456
1511
|
|
|
1457
|
-
for (const
|
|
1458
|
-
|
|
1512
|
+
for (const resourceLine of LinkedAffectedResources.getMarkdownLines({
|
|
1513
|
+
dashboardUrl: await DatabaseConfig.getDashboardUrl(),
|
|
1514
|
+
projectId: scheduledMaintenance.projectId!,
|
|
1515
|
+
resources: resources,
|
|
1516
|
+
})) {
|
|
1517
|
+
feedInfoInMarkdown += `${resourceLine}\n`;
|
|
1459
1518
|
}
|
|
1460
1519
|
|
|
1461
1520
|
feedInfoInMarkdown += `\n\n`;
|
|
@@ -1820,47 +1879,42 @@ ${(
|
|
|
1820
1879
|
shouldAddScheduledMaintenanceFeed = true;
|
|
1821
1880
|
}
|
|
1822
1881
|
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
)
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1882
|
+
/*
|
|
1883
|
+
* Any affected-resource list in the payload - not only monitors - is
|
|
1884
|
+
* a change to what the event affects. The event is read back rather
|
|
1885
|
+
* than the ids in the payload being looked up: the read is held to
|
|
1886
|
+
* this project, and it names the whole list the card now shows.
|
|
1887
|
+
*/
|
|
1888
|
+
const affectedResourcesChanged: boolean =
|
|
1889
|
+
LinkedAffectedResources.getRelations(this.getModel()).some(
|
|
1890
|
+
(relation: LinkedAffectedResourceRelation): boolean => {
|
|
1891
|
+
const value: unknown = (
|
|
1892
|
+
onUpdate.updateBy.data as Record<string, unknown>
|
|
1893
|
+
)[relation.column];
|
|
1894
|
+
|
|
1895
|
+
return Array.isArray(value) && value.length > 0;
|
|
1896
|
+
},
|
|
1897
|
+
);
|
|
1835
1898
|
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
.
|
|
1839
|
-
return monitorId !== null;
|
|
1840
|
-
});
|
|
1899
|
+
if (affectedResourcesChanged && onUpdate.updateBy.props.tenantId) {
|
|
1900
|
+
const projectId: ObjectID = onUpdate.updateBy.props
|
|
1901
|
+
.tenantId as ObjectID;
|
|
1841
1902
|
|
|
1842
|
-
const
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
},
|
|
1849
|
-
limit: LIMIT_PER_PROJECT,
|
|
1850
|
-
skip: 0,
|
|
1851
|
-
props: {
|
|
1852
|
-
isRoot: true,
|
|
1853
|
-
},
|
|
1854
|
-
});
|
|
1903
|
+
const resources: Array<LinkedAffectedResource> =
|
|
1904
|
+
await LinkedAffectedResources.readForScheduledMaintenance({
|
|
1905
|
+
service: this,
|
|
1906
|
+
projectId: projectId,
|
|
1907
|
+
scheduledMaintenanceId: scheduledMaintenanceId,
|
|
1908
|
+
});
|
|
1855
1909
|
|
|
1856
|
-
if (
|
|
1910
|
+
if (resources.length > 0) {
|
|
1857
1911
|
feedInfoInMarkdown += `\n\n**Resources Affected**:
|
|
1858
1912
|
|
|
1859
|
-
${
|
|
1860
|
-
.
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1913
|
+
${LinkedAffectedResources.getMarkdownLines({
|
|
1914
|
+
dashboardUrl: await DatabaseConfig.getDashboardUrl(),
|
|
1915
|
+
projectId: projectId,
|
|
1916
|
+
resources: resources,
|
|
1917
|
+
}).join("\n")}
|
|
1864
1918
|
`;
|
|
1865
1919
|
|
|
1866
1920
|
shouldAddScheduledMaintenanceFeed = true;
|
|
@@ -41,6 +41,15 @@ export class SmsService extends BaseService {
|
|
|
41
41
|
onCallDutyPolicyExecutionLogTimelineId?: ObjectID | undefined;
|
|
42
42
|
onCallScheduleId?: ObjectID | undefined;
|
|
43
43
|
teamId?: ObjectID | undefined;
|
|
44
|
+
/*
|
|
45
|
+
* Answer with an error, not success, when the Notification service
|
|
46
|
+
* deliberately does not send the SMS: the project has SMS notifications
|
|
47
|
+
* turned off, or too little SMS balance. The status page subscriber
|
|
48
|
+
* sends that count what they delivered pass it
|
|
49
|
+
* (SubscriberNotificationDeliveryRecord), so such an SMS counts as
|
|
50
|
+
* failed rather than sent.
|
|
51
|
+
*/
|
|
52
|
+
failIfNotSent?: boolean | undefined;
|
|
44
53
|
},
|
|
45
54
|
): Promise<HTTPResponse<EmptyResponseData>> {
|
|
46
55
|
const body: JSONObject = {
|
|
@@ -74,6 +83,7 @@ export class SmsService extends BaseService {
|
|
|
74
83
|
options.onCallDutyPolicyExecutionLogTimelineId?.toString(),
|
|
75
84
|
onCallScheduleId: options.onCallScheduleId?.toString(),
|
|
76
85
|
teamId: options.teamId?.toString(),
|
|
86
|
+
...(options.failIfNotSent ? { failIfNotSent: true } : {}),
|
|
77
87
|
};
|
|
78
88
|
|
|
79
89
|
return await API.post<EmptyResponseData>({
|