@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
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import LIMIT_MAX from "../../../Types/Database/LimitMax";
|
|
2
|
+
import OneUptimeDate from "../../../Types/Date";
|
|
3
|
+
|
|
4
|
+
/*
|
|
5
|
+
* How long the incident and episode subscriber jobs may spend sending, and
|
|
6
|
+
* how long a notification may sit In progress before it is taken to have been
|
|
7
|
+
* interrupted.
|
|
8
|
+
*
|
|
9
|
+
* A job sends each notification - an incident created, a state change, a
|
|
10
|
+
* public note, a postmortem, or an episode's - by awaiting every message at a
|
|
11
|
+
* bounded concurrency, so a send takes as long as its slowest subscribers
|
|
12
|
+
* rather than returning the moment the messages are queued. These numbers
|
|
13
|
+
* keep that bounded, and tie the job's timeout, a notification's send window
|
|
14
|
+
* and the sweeper's threshold together so they cannot drift apart:
|
|
15
|
+
*
|
|
16
|
+
* - SEND_CONCURRENCY messages are in flight at once, per notification.
|
|
17
|
+
* - SUBSCRIBERS_PER_READ subscribers are read from a status page at a time:
|
|
18
|
+
* LIMIT_MAX, the cap one read used to stop at silently. A page with more is
|
|
19
|
+
* read in batches (SubscriberNotificationFanOut).
|
|
20
|
+
* - A message still unanswered after SEND_TIMEOUT_IN_MS is counted failed and
|
|
21
|
+
* its slot freed. That is longer than any sender's own retries can take -
|
|
22
|
+
* the Notification service tries SMTP three times with a 60 second connect
|
|
23
|
+
* timeout each (about 3 minutes 5 seconds), and the Slack and webhook
|
|
24
|
+
* senders retry three times with 2, 4 and 8 second backoffs - so it only
|
|
25
|
+
* cuts off a request that hangs. The request itself is not cancelled.
|
|
26
|
+
* - A notification starts no new message once SEND_WINDOW_IN_MS has passed
|
|
27
|
+
* since it was claimed. What it has not reached is recorded as not sent,
|
|
28
|
+
* and the notification settles as Failed.
|
|
29
|
+
*
|
|
30
|
+
* The math, for one full read of a status page: 10,000 subscribers at 20 in
|
|
31
|
+
* flight is 500 rounds, and 20 minutes over 500 rounds allows 2.4 seconds a
|
|
32
|
+
* message on average. An email, SMS or webhook through the Notification
|
|
33
|
+
* service normally answers in well under a second, so a 10,000-subscriber
|
|
34
|
+
* page fits with room to spare, and at half a second a message one
|
|
35
|
+
* notification reaches about 48,000 subscribers in its window.
|
|
36
|
+
*
|
|
37
|
+
* - One notification can therefore take at most NOTIFICATION_MAX_IN_MS: its
|
|
38
|
+
* send window, plus the timeout of the messages still in flight when the
|
|
39
|
+
* window closes, plus a minute for the feed item and the status write.
|
|
40
|
+
* - JOB_TIMEOUT_IN_MS is each job's RunCron timeoutInMS. A run claims a new
|
|
41
|
+
* notification only while that notification could still finish inside the
|
|
42
|
+
* job's timeout (LATEST_CLAIM_IN_MS into the run), so a run never outlives
|
|
43
|
+
* its timeout: a timed-out queue job is only stopped being waited for,
|
|
44
|
+
* never cancelled, and would otherwise carry on sending untracked. The
|
|
45
|
+
* notifications it leaves Pending are claimed by the runs that follow, one
|
|
46
|
+
* a minute, which can run alongside it: a claim is atomic
|
|
47
|
+
* (SubscriberNotificationClaim), so each notification is sent once. How
|
|
48
|
+
* many runs of a job may be sending at once, across every worker, is
|
|
49
|
+
* bounded too (SubscriberNotificationRunLimit), so slow sends cannot fill
|
|
50
|
+
* the Worker queue every other cron shares.
|
|
51
|
+
* - STUCK_AFTER_IN_MS is when the sweeper
|
|
52
|
+
* (StatusPageSubscriber:TimeoutStuckNotifications) takes a notification
|
|
53
|
+
* still In progress to have been interrupted - its worker crashed, was
|
|
54
|
+
* redeployed or lost its database connection - and marks it Failed. A
|
|
55
|
+
* running send is never In progress that long, so the margin over the job
|
|
56
|
+
* timeout only has to cover clock skew between the worker and the database.
|
|
57
|
+
*/
|
|
58
|
+
export default class SubscriberNotificationTiming {
|
|
59
|
+
public static readonly SEND_CONCURRENCY: number = 20;
|
|
60
|
+
|
|
61
|
+
public static readonly SUBSCRIBERS_PER_READ: number = LIMIT_MAX;
|
|
62
|
+
|
|
63
|
+
public static readonly SEND_TIMEOUT_IN_MS: number =
|
|
64
|
+
OneUptimeDate.convertMinutesToMilliseconds(4);
|
|
65
|
+
|
|
66
|
+
public static readonly SEND_WINDOW_IN_MS: number =
|
|
67
|
+
OneUptimeDate.convertMinutesToMilliseconds(20);
|
|
68
|
+
|
|
69
|
+
public static readonly SETTLE_ALLOWANCE_IN_MS: number =
|
|
70
|
+
OneUptimeDate.convertMinutesToMilliseconds(1);
|
|
71
|
+
|
|
72
|
+
public static readonly NOTIFICATION_MAX_IN_MS: number =
|
|
73
|
+
SubscriberNotificationTiming.SEND_WINDOW_IN_MS +
|
|
74
|
+
SubscriberNotificationTiming.SEND_TIMEOUT_IN_MS +
|
|
75
|
+
SubscriberNotificationTiming.SETTLE_ALLOWANCE_IN_MS;
|
|
76
|
+
|
|
77
|
+
public static readonly JOB_TIMEOUT_IN_MS: number =
|
|
78
|
+
OneUptimeDate.convertMinutesToMilliseconds(30);
|
|
79
|
+
|
|
80
|
+
public static readonly LATEST_CLAIM_IN_MS: number =
|
|
81
|
+
SubscriberNotificationTiming.JOB_TIMEOUT_IN_MS -
|
|
82
|
+
SubscriberNotificationTiming.NOTIFICATION_MAX_IN_MS;
|
|
83
|
+
|
|
84
|
+
public static readonly STUCK_AFTER_IN_MS: number =
|
|
85
|
+
SubscriberNotificationTiming.JOB_TIMEOUT_IN_MS +
|
|
86
|
+
OneUptimeDate.convertMinutesToMilliseconds(10);
|
|
87
|
+
|
|
88
|
+
// The clock of one job run, started when the run starts.
|
|
89
|
+
public static startRun(now?: number): SubscriberNotificationRunClock {
|
|
90
|
+
return new SubscriberNotificationRunClock(now ?? Date.now());
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// The send window of one notification, started when it is claimed.
|
|
94
|
+
public static startSendWindow(
|
|
95
|
+
now?: number,
|
|
96
|
+
): SubscriberNotificationSendWindow {
|
|
97
|
+
return new SubscriberNotificationSendWindow(
|
|
98
|
+
(now ?? Date.now()) + SubscriberNotificationTiming.SEND_WINDOW_IN_MS,
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export class SubscriberNotificationRunClock {
|
|
104
|
+
private readonly startedAt: number;
|
|
105
|
+
|
|
106
|
+
public constructor(startedAt: number) {
|
|
107
|
+
this.startedAt = startedAt;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/*
|
|
111
|
+
* Whether this run may still claim a notification: one claimed now could
|
|
112
|
+
* finish before the run's timeout.
|
|
113
|
+
*/
|
|
114
|
+
public canClaimAnotherNotification(now?: number): boolean {
|
|
115
|
+
return (
|
|
116
|
+
(now ?? Date.now()) - this.startedAt <=
|
|
117
|
+
SubscriberNotificationTiming.LATEST_CLAIM_IN_MS
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export class SubscriberNotificationSendWindow {
|
|
123
|
+
public readonly closesAt: number;
|
|
124
|
+
|
|
125
|
+
public constructor(closesAt: number) {
|
|
126
|
+
this.closesAt = closesAt;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Whether a new message may still be started.
|
|
130
|
+
public isOpen(now?: number): boolean {
|
|
131
|
+
return (now ?? Date.now()) < this.closesAt;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
import Incident from "../../../Models/DatabaseModels/Incident";
|
|
2
|
+
import IncidentCustomField from "../../../Models/DatabaseModels/IncidentCustomField";
|
|
3
|
+
import BaseModel, {
|
|
4
|
+
DatabaseBaseModelType,
|
|
5
|
+
} from "../../../Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel";
|
|
6
|
+
import DatabaseCommonInteractionProps from "../../../Types/BaseDatabase/DatabaseCommonInteractionProps";
|
|
7
|
+
import DatabaseCommonInteractionPropsUtil, {
|
|
8
|
+
PermissionType,
|
|
9
|
+
} from "../../../Types/BaseDatabase/DatabaseCommonInteractionPropsUtil";
|
|
10
|
+
import { CUSTOM_FIELD_TEMPLATE_VARIABLE_PREFIX } from "../../../Types/CustomField/CustomFieldVariableKey";
|
|
11
|
+
import PermissionScope from "../../../Types/Database/AccessControl/PermissionScope";
|
|
12
|
+
import NotAuthorizedException from "../../../Types/Exception/NotAuthorizedException";
|
|
13
|
+
import Permission, {
|
|
14
|
+
PermissionHelper,
|
|
15
|
+
UserPermission,
|
|
16
|
+
} from "../../../Types/Permission";
|
|
17
|
+
|
|
18
|
+
/*
|
|
19
|
+
* WHO MAY PLACE INCIDENT RECORDS IN A SUBSCRIBER TEMPLATE.
|
|
20
|
+
*
|
|
21
|
+
* A custom subscriber notification template can place {{incidentLabels}} and
|
|
22
|
+
* any {{customFields.<key>}} - values from the team's incident records, which
|
|
23
|
+
* the status page does not show, marked for subscribers or not
|
|
24
|
+
* (SubscriberNotificationTemplateVariables.getIncidentRecordPlaceholders).
|
|
25
|
+
* Templates are written by the status page roles (StatusPageAdmin,
|
|
26
|
+
* StatusPageMember), which cannot read incidents; and a Slack, Teams or
|
|
27
|
+
* webhook subscriber can be added by the same roles, pointing at an address
|
|
28
|
+
* they own. Without this check such a role could send itself every
|
|
29
|
+
* incident's custom fields - guessing keys, which come predictably from
|
|
30
|
+
* field names, many at once, since a placeholder with no value is left as
|
|
31
|
+
* written.
|
|
32
|
+
*
|
|
33
|
+
* So a template may place them only if whoever writes it may read them
|
|
34
|
+
* directly: incidents, the column the value comes from (Incident.customFields
|
|
35
|
+
* or Incident.labels) and, for custom fields, the field definitions. And for
|
|
36
|
+
* every incident of the project, since a template reaches every incident
|
|
37
|
+
* that reaches its status pages: a grant limited to labels or to owned
|
|
38
|
+
* incidents does not count, and a block on any of those permissions refuses.
|
|
39
|
+
*
|
|
40
|
+
* The permissions are read from the models' own access control, so they
|
|
41
|
+
* follow any change to it. Root and master admin writes are not checked.
|
|
42
|
+
*/
|
|
43
|
+
|
|
44
|
+
interface AccessRequirement {
|
|
45
|
+
// What the caller must be able to read, for the refusal.
|
|
46
|
+
description: string;
|
|
47
|
+
permissions: Array<Permission>;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export default class SubscriberTemplateIncidentRecordAccess {
|
|
51
|
+
/**
|
|
52
|
+
* Refuses a write that places these placeholders (from
|
|
53
|
+
* getIncidentRecordPlaceholders) unless the caller may read what they
|
|
54
|
+
* read, for every incident of the project. Does nothing when there are
|
|
55
|
+
* none, or for root and master admin.
|
|
56
|
+
*/
|
|
57
|
+
public static assertCanPlace(data: {
|
|
58
|
+
placeholders: Array<string>;
|
|
59
|
+
props: DatabaseCommonInteractionProps;
|
|
60
|
+
}): void {
|
|
61
|
+
if (
|
|
62
|
+
data.placeholders.length === 0 ||
|
|
63
|
+
data.props.isRoot ||
|
|
64
|
+
data.props.isMasterAdmin
|
|
65
|
+
) {
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
const unrestricted: Array<Permission> =
|
|
70
|
+
SubscriberTemplateIncidentRecordAccess.getUnrestrictedPermissions(
|
|
71
|
+
data.props,
|
|
72
|
+
);
|
|
73
|
+
const blocked: Array<Permission> =
|
|
74
|
+
DatabaseCommonInteractionPropsUtil.getUserPermissions(
|
|
75
|
+
data.props,
|
|
76
|
+
PermissionType.Block,
|
|
77
|
+
).map((row: UserPermission): Permission => {
|
|
78
|
+
return row.permission;
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
for (const requirement of SubscriberTemplateIncidentRecordAccess.getRequirements(
|
|
82
|
+
data.placeholders,
|
|
83
|
+
)) {
|
|
84
|
+
const isGranted: boolean = PermissionHelper.doesPermissionsIntersect(
|
|
85
|
+
unrestricted,
|
|
86
|
+
requirement.permissions,
|
|
87
|
+
);
|
|
88
|
+
const isBlocked: boolean = PermissionHelper.doesPermissionsIntersect(
|
|
89
|
+
blocked,
|
|
90
|
+
requirement.permissions,
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
if (isGranted && !isBlocked) {
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const placeholders: string = data.placeholders
|
|
98
|
+
.map((name: string): string => {
|
|
99
|
+
return `{{${name}}}`;
|
|
100
|
+
})
|
|
101
|
+
.join(", ");
|
|
102
|
+
|
|
103
|
+
throw new NotAuthorizedException(
|
|
104
|
+
`Placing ${placeholders} in a subscriber notification template needs permission to ${requirement.description} for every incident in the project: these values come from your team's incident records, which the status page does not show. You need one of these permissions, not limited to some labels or to incidents you own: ${PermissionHelper.getPermissionTitles(
|
|
105
|
+
requirement.permissions,
|
|
106
|
+
).join(", ")}.`,
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/*
|
|
112
|
+
* What these placeholders need: reading incidents, and the column each
|
|
113
|
+
* one reads - Incident.labels for {{incidentLabels}}; Incident.customFields
|
|
114
|
+
* and the field definitions for {{customFields.<key>}}.
|
|
115
|
+
*/
|
|
116
|
+
public static getRequirements(
|
|
117
|
+
placeholders: Array<string>,
|
|
118
|
+
): Array<AccessRequirement> {
|
|
119
|
+
const requirements: Array<AccessRequirement> = [
|
|
120
|
+
{
|
|
121
|
+
description: "read incidents",
|
|
122
|
+
permissions: this.getTableReadPermissions(Incident),
|
|
123
|
+
},
|
|
124
|
+
];
|
|
125
|
+
|
|
126
|
+
if (
|
|
127
|
+
placeholders.some((name: string): boolean => {
|
|
128
|
+
return name.startsWith(CUSTOM_FIELD_TEMPLATE_VARIABLE_PREFIX);
|
|
129
|
+
})
|
|
130
|
+
) {
|
|
131
|
+
requirements.push(
|
|
132
|
+
{
|
|
133
|
+
description: "read incident custom field values",
|
|
134
|
+
permissions: this.getColumnReadPermissions(Incident, "customFields"),
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
description: "read incident custom fields",
|
|
138
|
+
permissions: this.getTableReadPermissions(IncidentCustomField),
|
|
139
|
+
},
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (
|
|
144
|
+
placeholders.some((name: string): boolean => {
|
|
145
|
+
return !name.startsWith(CUSTOM_FIELD_TEMPLATE_VARIABLE_PREFIX);
|
|
146
|
+
})
|
|
147
|
+
) {
|
|
148
|
+
requirements.push({
|
|
149
|
+
description: "read incident labels",
|
|
150
|
+
permissions: this.getColumnReadPermissions(Incident, "labels"),
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
return requirements;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/*
|
|
158
|
+
* The caller's granted permissions that reach every record, read as the
|
|
159
|
+
* read checks read them (PermissionHelper.getNonAccessControlPermissions,
|
|
160
|
+
* OwnedScopePermission): a row scoped to All, or a Labels (or legacy
|
|
161
|
+
* unscoped) row with no labels. A row limited to labels does not, nor one
|
|
162
|
+
* limited to owned records - except for a project-wide role that cannot
|
|
163
|
+
* be scoped (Project Owner, Project Admin), whose stray Owned scope the
|
|
164
|
+
* read checks ignore too.
|
|
165
|
+
*/
|
|
166
|
+
private static getUnrestrictedPermissions(
|
|
167
|
+
props: DatabaseCommonInteractionProps,
|
|
168
|
+
): Array<Permission> {
|
|
169
|
+
return DatabaseCommonInteractionPropsUtil.getUserPermissions(
|
|
170
|
+
props,
|
|
171
|
+
PermissionType.Allow,
|
|
172
|
+
)
|
|
173
|
+
.filter((row: UserPermission): boolean => {
|
|
174
|
+
if (row.scope === PermissionScope.All) {
|
|
175
|
+
return true;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
if (row.scope === PermissionScope.Owned) {
|
|
179
|
+
return !PermissionHelper.isScopeApplicable(row.permission);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
return !row.labelIds || row.labelIds.length === 0;
|
|
183
|
+
})
|
|
184
|
+
.map((row: UserPermission): Permission => {
|
|
185
|
+
return row.permission;
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// As the table check reads them, the operational resource wildcard included.
|
|
190
|
+
private static getTableReadPermissions(
|
|
191
|
+
modelType: DatabaseBaseModelType,
|
|
192
|
+
): Array<Permission> {
|
|
193
|
+
const model: BaseModel = new modelType();
|
|
194
|
+
const permissions: Array<Permission> = [...model.readRecordPermissions];
|
|
195
|
+
|
|
196
|
+
if (
|
|
197
|
+
model.isOperationalResource &&
|
|
198
|
+
!permissions.includes(Permission.ReadAllOperationalResources)
|
|
199
|
+
) {
|
|
200
|
+
permissions.push(Permission.ReadAllOperationalResources);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
return permissions;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
// As the select check reads them: no wildcard reaches a column.
|
|
207
|
+
private static getColumnReadPermissions(
|
|
208
|
+
modelType: DatabaseBaseModelType,
|
|
209
|
+
columnName: string,
|
|
210
|
+
): Array<Permission> {
|
|
211
|
+
return [
|
|
212
|
+
...(new modelType().getColumnAccessControlFor(columnName)?.read || []),
|
|
213
|
+
];
|
|
214
|
+
}
|
|
215
|
+
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import StatusPageResource from "../../Models/DatabaseModels/StatusPageResource";
|
|
2
2
|
import Dictionary from "../../Types/Dictionary";
|
|
3
|
+
import SafeHtml from "../../Types/SafeHtml";
|
|
3
4
|
|
|
4
5
|
export interface GetResourcesGroupedByGroupNameOptions {
|
|
5
6
|
resources: Array<StatusPageResource>;
|
|
@@ -16,6 +17,12 @@ export const HTML_RESOURCE_GROUP_SEPARATOR: string = "<br/>";
|
|
|
16
17
|
*/
|
|
17
18
|
export const PLAIN_TEXT_RESOURCE_GROUP_SEPARATOR: string = "; ";
|
|
18
19
|
|
|
20
|
+
type FormatNameFunction = (name: string) => string;
|
|
21
|
+
|
|
22
|
+
const asWritten: FormatNameFunction = (name: string): string => {
|
|
23
|
+
return name;
|
|
24
|
+
};
|
|
25
|
+
|
|
19
26
|
export default class StatusPageResourceUtil {
|
|
20
27
|
/**
|
|
21
28
|
* Formats an array of StatusPageResource items into an HTML string grouped by their resource group.
|
|
@@ -24,8 +31,18 @@ export default class StatusPageResourceUtil {
|
|
|
24
31
|
* If resources are grouped, returns one group per line, like:
|
|
25
32
|
* "EU: Infrastructure, Website<br/>UK: Infrastructure, API"
|
|
26
33
|
*
|
|
34
|
+
* The result is HTML: every resource name, group name and the default
|
|
35
|
+
* value is HTML-escaped before it is joined, and the only markup is the
|
|
36
|
+
* "<br/>" between groups. A project member names resources and groups, and
|
|
37
|
+
* the default subscriber emails put this list into their raw-HTML slot, so
|
|
38
|
+
* a name such as `<a href="https://evil.example">Checkout</a>` would
|
|
39
|
+
* otherwise arrive as a live link. That is also what makes it safe to hand
|
|
40
|
+
* a custom email template as SafeHtml.
|
|
41
|
+
*
|
|
27
42
|
* Use this only where the value is rendered as HTML (email bodies). Use
|
|
28
|
-
* getResourcesGroupedByGroupNameAsPlainText everywhere else
|
|
43
|
+
* getResourcesGroupedByGroupNameAsPlainText everywhere else: it is not
|
|
44
|
+
* escaped, because SMS, Slack, Teams, subjects and webhooks show text as
|
|
45
|
+
* written.
|
|
29
46
|
*
|
|
30
47
|
* @param resources - Array of StatusPageResource items with displayName, statusPageGroupId, and optionally statusPageGroup.name
|
|
31
48
|
* @param defaultValue - Value to return if no resources (defaults to "")
|
|
@@ -35,11 +52,12 @@ export default class StatusPageResourceUtil {
|
|
|
35
52
|
resources: Array<StatusPageResource>,
|
|
36
53
|
defaultValue: string = "",
|
|
37
54
|
): string {
|
|
38
|
-
return StatusPageResourceUtil.formatResourcesGroupedByGroupName(
|
|
39
|
-
resources,
|
|
40
|
-
defaultValue,
|
|
41
|
-
HTML_RESOURCE_GROUP_SEPARATOR,
|
|
42
|
-
|
|
55
|
+
return StatusPageResourceUtil.formatResourcesGroupedByGroupName({
|
|
56
|
+
resources: resources,
|
|
57
|
+
defaultValue: defaultValue,
|
|
58
|
+
groupSeparator: HTML_RESOURCE_GROUP_SEPARATOR,
|
|
59
|
+
formatName: SafeHtml.escape,
|
|
60
|
+
});
|
|
43
61
|
}
|
|
44
62
|
|
|
45
63
|
/**
|
|
@@ -55,18 +73,28 @@ export default class StatusPageResourceUtil {
|
|
|
55
73
|
resources: Array<StatusPageResource>,
|
|
56
74
|
defaultValue: string = "",
|
|
57
75
|
): string {
|
|
58
|
-
return StatusPageResourceUtil.formatResourcesGroupedByGroupName(
|
|
59
|
-
resources,
|
|
60
|
-
defaultValue,
|
|
61
|
-
PLAIN_TEXT_RESOURCE_GROUP_SEPARATOR,
|
|
62
|
-
|
|
76
|
+
return StatusPageResourceUtil.formatResourcesGroupedByGroupName({
|
|
77
|
+
resources: resources,
|
|
78
|
+
defaultValue: defaultValue,
|
|
79
|
+
groupSeparator: PLAIN_TEXT_RESOURCE_GROUP_SEPARATOR,
|
|
80
|
+
formatName: asWritten,
|
|
81
|
+
});
|
|
63
82
|
}
|
|
64
83
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
84
|
+
/*
|
|
85
|
+
* Groups are keyed by the name as written, so two groups are merged only
|
|
86
|
+
* when their names really are the same; formatName (the HTML escaping, for
|
|
87
|
+
* the HTML form) is applied to each piece of text as it is written out.
|
|
88
|
+
*/
|
|
89
|
+
private static formatResourcesGroupedByGroupName(data: {
|
|
90
|
+
resources: Array<StatusPageResource>;
|
|
91
|
+
defaultValue: string;
|
|
92
|
+
groupSeparator: string;
|
|
93
|
+
formatName: FormatNameFunction;
|
|
94
|
+
}): string {
|
|
95
|
+
const { resources, groupSeparator, formatName } = data;
|
|
96
|
+
const defaultValue: string = formatName(data.defaultValue);
|
|
97
|
+
|
|
70
98
|
if (!resources || resources.length === 0) {
|
|
71
99
|
return defaultValue;
|
|
72
100
|
}
|
|
@@ -83,9 +111,10 @@ export default class StatusPageResourceUtil {
|
|
|
83
111
|
.map((r: StatusPageResource) => {
|
|
84
112
|
return r.displayName;
|
|
85
113
|
})
|
|
86
|
-
.filter((name: string | undefined) => {
|
|
87
|
-
return name;
|
|
114
|
+
.filter((name: string | undefined): name is string => {
|
|
115
|
+
return Boolean(name);
|
|
88
116
|
})
|
|
117
|
+
.map(formatName)
|
|
89
118
|
.join(", ") || ""
|
|
90
119
|
);
|
|
91
120
|
}
|
|
@@ -119,13 +148,15 @@ export default class StatusPageResourceUtil {
|
|
|
119
148
|
// Add grouped resources
|
|
120
149
|
for (const groupName in resourcesByGroup) {
|
|
121
150
|
const groupResources: Array<string> = resourcesByGroup[groupName]!;
|
|
122
|
-
formattedGroups.push(
|
|
151
|
+
formattedGroups.push(
|
|
152
|
+
`${formatName(groupName)}: ${groupResources.map(formatName).join(", ")}`,
|
|
153
|
+
);
|
|
123
154
|
}
|
|
124
155
|
|
|
125
156
|
// Add ungrouped resources on separate lines (without "Other" label)
|
|
126
157
|
if (ungroupedResources.length > 0) {
|
|
127
158
|
for (const resourceName of ungroupedResources) {
|
|
128
|
-
formattedGroups.push(resourceName);
|
|
159
|
+
formattedGroups.push(formatName(resourceName));
|
|
129
160
|
}
|
|
130
161
|
}
|
|
131
162
|
|