@oneuptime/common 14.0.7 → 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/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/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 +14 -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/DatabaseService.ts +93 -10
- 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 +1535 -65
- package/Server/Services/IncidentStateTimelineService.ts +13 -0
- package/Server/Services/IncidentTemplateService.ts +109 -0
- package/Server/Services/ScheduledMaintenancePublicNoteService.ts +30 -1
- package/Server/Services/ScheduledMaintenanceService.ts +68 -18
- 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/Types/Markdown.ts +153 -6
- package/Server/Types/Workflow/Components/Email.ts +61 -2
- package/Server/Utils/CustomField/CustomFieldRename.ts +378 -0
- package/Server/Utils/DataSource/EgressGuard.ts +66 -21
- package/Server/Utils/Mail/PinnedSmtpSocket.ts +130 -0
- package/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.ts +10 -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/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/CustomFieldsSettingsIncidentOptions.test.tsx +357 -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 +242 -5
- package/Tests/App/Dashboard/IncidentChangeStateNotifyDefault.test.tsx +91 -1
- 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/PublicNotePagesNotifyDefault.test.tsx +113 -1
- 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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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 +14 -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/DatabaseService.js +56 -7
- package/build/dist/Server/Services/DatabaseService.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 +1052 -0
- 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/ScheduledMaintenancePublicNoteService.js +26 -1
- package/build/dist/Server/Services/ScheduledMaintenancePublicNoteService.js.map +1 -1
- package/build/dist/Server/Services/ScheduledMaintenanceService.js +47 -17
- 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/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/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/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/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/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/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/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/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,421 @@
|
|
|
1
|
+
import Incident from "../../../Models/DatabaseModels/Incident";
|
|
2
|
+
import StatusPage from "../../../Models/DatabaseModels/StatusPage";
|
|
3
|
+
import StatusPageSubscriberNotificationTemplate from "../../../Models/DatabaseModels/StatusPageSubscriberNotificationTemplate";
|
|
4
|
+
import { StatusPageApiRoute } from "../../../ServiceRoute";
|
|
5
|
+
import Hostname from "../../../Types/API/Hostname";
|
|
6
|
+
import Protocol from "../../../Types/API/Protocol";
|
|
7
|
+
import URL from "../../../Types/API/URL";
|
|
8
|
+
import OneUptimeDate from "../../../Types/Date";
|
|
9
|
+
import { EmailEnvelope } from "../../../Types/Email/EmailMessage";
|
|
10
|
+
import EmailTemplateType from "../../../Types/Email/EmailTemplateType";
|
|
11
|
+
import BadDataException from "../../../Types/Exception/BadDataException";
|
|
12
|
+
import { JSONObject } from "../../../Types/JSON";
|
|
13
|
+
import ObjectID from "../../../Types/ObjectID";
|
|
14
|
+
import StatusPageSubscriberNotificationEventType from "../../../Types/StatusPage/StatusPageSubscriberNotificationEventType";
|
|
15
|
+
import StatusPageSubscriberNotificationMethod from "../../../Types/StatusPage/StatusPageSubscriberNotificationMethod";
|
|
16
|
+
import {
|
|
17
|
+
SubscriberEmailTemplateChoice,
|
|
18
|
+
SubscriberEmailTemplateChoiceReason,
|
|
19
|
+
} from "../../../Types/StatusPage/SubscriberNotificationPreview";
|
|
20
|
+
import { Service as StatusPageServiceType } from "../../Services/StatusPageService";
|
|
21
|
+
import StatusPageSubscriberNotificationTemplateService, {
|
|
22
|
+
Service as StatusPageSubscriberNotificationTemplateServiceClass,
|
|
23
|
+
SubscriberNotificationEmailBodyTemplateVariables,
|
|
24
|
+
} from "../../Services/StatusPageSubscriberNotificationTemplateService";
|
|
25
|
+
import IncidentTemplateVariableBuilder, {
|
|
26
|
+
IncidentStatusPageTemplateVariables,
|
|
27
|
+
IncidentTemplateVariables,
|
|
28
|
+
} from "./IncidentTemplateVariableBuilder";
|
|
29
|
+
|
|
30
|
+
/*
|
|
31
|
+
* The email a status page's subscribers get about an incident - its subject
|
|
32
|
+
* and its body, from the page's custom template or the default one - for the
|
|
33
|
+
* 'incident created' and public note (posted and updated) notifications.
|
|
34
|
+
*
|
|
35
|
+
* The one code path for it. The subscriber jobs send what this builds
|
|
36
|
+
* (Workers/Jobs/Incident/SendNotificationToSubscribers and
|
|
37
|
+
* Workers/Jobs/IncidentPublicNote/SendNotificationToSubscribers), and "Preview
|
|
38
|
+
* notification" and "Send test to me" show and send the same thing
|
|
39
|
+
* (Notification/API/SubscriberNotificationPreview), rendered by the same
|
|
40
|
+
* mailer (Notification MailService.render). A preview therefore cannot show
|
|
41
|
+
* one email while subscribers are sent another.
|
|
42
|
+
*
|
|
43
|
+
* It builds on what the jobs already share, rather than repeating it:
|
|
44
|
+
*
|
|
45
|
+
* - IncidentTemplateVariableBuilder for the values, in each channel's
|
|
46
|
+
* format (buildTemplateVariables reads them for an event), and
|
|
47
|
+
* - SubscriberNotificationTemplateCompiler, through the template service,
|
|
48
|
+
* for a custom template: compileEmailBodyTemplate for the body, which
|
|
49
|
+
* escapes every plain value, and compileTemplate for the subject.
|
|
50
|
+
*
|
|
51
|
+
* The page's custom email template is used only when it has a body and the
|
|
52
|
+
* page sends through its own SMTP server, as the jobs have always done;
|
|
53
|
+
* templateChoice says which email the page's subscribers get, and why.
|
|
54
|
+
*
|
|
55
|
+
* Building an email has no side effects. Sending one does: the custom field
|
|
56
|
+
* values it carries are recorded for the incident feed, and a Rich text
|
|
57
|
+
* field's inline images are made public so the recipient can load them. So a
|
|
58
|
+
* job calls recordSending before each message goes out, and a preview never
|
|
59
|
+
* does - previewing an email must not publish anything.
|
|
60
|
+
*/
|
|
61
|
+
|
|
62
|
+
// Which notification the email is for.
|
|
63
|
+
export enum SubscriberIncidentEmailEvent {
|
|
64
|
+
IncidentCreated = "IncidentCreated",
|
|
65
|
+
IncidentPublicNoteCreated = "IncidentPublicNoteCreated",
|
|
66
|
+
IncidentPublicNoteUpdated = "IncidentPublicNoteUpdated",
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
interface SubscriberIncidentEmailCopy {
|
|
70
|
+
// The custom templates this event's email is looked up by.
|
|
71
|
+
templateEventType: StatusPageSubscriberNotificationEventType;
|
|
72
|
+
// The default email's template.
|
|
73
|
+
defaultTemplateType: EmailTemplateType;
|
|
74
|
+
// The default email's subject, before the incident title.
|
|
75
|
+
defaultSubjectPrefix: string;
|
|
76
|
+
// A custom template with no subject of its own: before the incident title.
|
|
77
|
+
customTemplateSubjectPrefix: string;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const EMAIL_COPY: Record<
|
|
81
|
+
SubscriberIncidentEmailEvent,
|
|
82
|
+
SubscriberIncidentEmailCopy
|
|
83
|
+
> = {
|
|
84
|
+
[SubscriberIncidentEmailEvent.IncidentCreated]: {
|
|
85
|
+
templateEventType:
|
|
86
|
+
StatusPageSubscriberNotificationEventType.SubscriberIncidentCreated,
|
|
87
|
+
defaultTemplateType: EmailTemplateType.SubscriberIncidentCreated,
|
|
88
|
+
defaultSubjectPrefix: "[Incident] ",
|
|
89
|
+
customTemplateSubjectPrefix: "[Incident] ",
|
|
90
|
+
},
|
|
91
|
+
[SubscriberIncidentEmailEvent.IncidentPublicNoteCreated]: {
|
|
92
|
+
templateEventType:
|
|
93
|
+
StatusPageSubscriberNotificationEventType.SubscriberIncidentNoteCreated,
|
|
94
|
+
defaultTemplateType: EmailTemplateType.SubscriberIncidentNoteCreated,
|
|
95
|
+
defaultSubjectPrefix: "[Update Incident] ",
|
|
96
|
+
customTemplateSubjectPrefix: "[Incident Update] ",
|
|
97
|
+
},
|
|
98
|
+
[SubscriberIncidentEmailEvent.IncidentPublicNoteUpdated]: {
|
|
99
|
+
templateEventType:
|
|
100
|
+
StatusPageSubscriberNotificationEventType.SubscriberIncidentNoteUpdated,
|
|
101
|
+
defaultTemplateType: EmailTemplateType.SubscriberIncidentNoteUpdated,
|
|
102
|
+
defaultSubjectPrefix: "[Incident Note Updated] ",
|
|
103
|
+
customTemplateSubjectPrefix: "[Incident Note Updated] ",
|
|
104
|
+
},
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
// One subscriber's email, ready for the mailer.
|
|
108
|
+
export interface SubscriberIncidentEmail {
|
|
109
|
+
// The subject as it is sent: final text, never compiled again.
|
|
110
|
+
subject: string;
|
|
111
|
+
/*
|
|
112
|
+
* Everything the mailer takes but the recipient: the template and its
|
|
113
|
+
* variables, and the subject. MailService.sendMail sends it (with toEmail
|
|
114
|
+
* added) and Notification MailService.render renders it.
|
|
115
|
+
*/
|
|
116
|
+
envelope: EmailEnvelope;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// One status page's email, before it is addressed to anyone.
|
|
120
|
+
export interface SubscriberIncidentStatusPageEmail {
|
|
121
|
+
// Which email the page's subscribers get, and why.
|
|
122
|
+
templateChoice: SubscriberEmailTemplateChoice;
|
|
123
|
+
/*
|
|
124
|
+
* The email one subscriber gets: the page's email, with the subscriber's
|
|
125
|
+
* own unsubscribe link. Pure: it can be called for a preview.
|
|
126
|
+
*/
|
|
127
|
+
forSubscriber: (data: { unsubscribeUrl: string }) => SubscriberIncidentEmail;
|
|
128
|
+
/*
|
|
129
|
+
* An email is about to go out: records the custom field values it carries
|
|
130
|
+
* (for the incident feed) and makes their inline images public. Awaited
|
|
131
|
+
* before each send. Never called for a preview. Never throws.
|
|
132
|
+
*/
|
|
133
|
+
recordSending: () => Promise<void>;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export default class SubscriberIncidentEmailBuilder {
|
|
137
|
+
/**
|
|
138
|
+
* The values every message of this event is filled with, on every
|
|
139
|
+
* channel, read once per send (IncidentTemplateVariableBuilder).
|
|
140
|
+
*
|
|
141
|
+
* The incident needs projectId, title, incidentSeverity.name, labels.name
|
|
142
|
+
* and customFields; a public note's also currentIncidentState.name.
|
|
143
|
+
* statusPages are the pages the send reaches, which name
|
|
144
|
+
* {{affectedStatusPages}}. A public note's event takes the note and when
|
|
145
|
+
* it says it was posted - an update reads it fresh from the row, and only a
|
|
146
|
+
* note with none falls back to now.
|
|
147
|
+
*/
|
|
148
|
+
public static async buildTemplateVariables(data: {
|
|
149
|
+
event: SubscriberIncidentEmailEvent;
|
|
150
|
+
incident: Incident;
|
|
151
|
+
statusPages: Array<StatusPage>;
|
|
152
|
+
note?:
|
|
153
|
+
| {
|
|
154
|
+
text: string | null | undefined;
|
|
155
|
+
postedAt: Date | null | undefined;
|
|
156
|
+
}
|
|
157
|
+
| undefined;
|
|
158
|
+
}): Promise<IncidentTemplateVariables> {
|
|
159
|
+
if (data.event === SubscriberIncidentEmailEvent.IncidentCreated) {
|
|
160
|
+
return IncidentTemplateVariableBuilder.build({
|
|
161
|
+
incident: data.incident,
|
|
162
|
+
statusPages: data.statusPages,
|
|
163
|
+
markdownVariables: {
|
|
164
|
+
incidentDescription: data.incident.description,
|
|
165
|
+
},
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
return IncidentTemplateVariableBuilder.build({
|
|
170
|
+
incident: data.incident,
|
|
171
|
+
statusPages: data.statusPages,
|
|
172
|
+
markdownVariables: {
|
|
173
|
+
note: data.note?.text,
|
|
174
|
+
},
|
|
175
|
+
textVariables: {
|
|
176
|
+
incidentState: data.incident.currentIncidentState?.name || "",
|
|
177
|
+
postedAt: OneUptimeDate.getDateAsUserFriendlyFormattedString(
|
|
178
|
+
data.note?.postedAt || OneUptimeDate.getCurrentDate(),
|
|
179
|
+
),
|
|
180
|
+
},
|
|
181
|
+
});
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
/*
|
|
185
|
+
* The incident on the status page, or the status page itself for an
|
|
186
|
+
* incident that has no id yet (one being previewed before it is declared).
|
|
187
|
+
*/
|
|
188
|
+
public static getDetailsUrl(data: {
|
|
189
|
+
statusPageUrl: string;
|
|
190
|
+
incidentId: ObjectID | null | undefined;
|
|
191
|
+
}): string {
|
|
192
|
+
return data.incidentId && data.statusPageUrl
|
|
193
|
+
? URL.fromString(data.statusPageUrl)
|
|
194
|
+
.addRoute(`/incidents/${data.incidentId.toString()}`)
|
|
195
|
+
.toString()
|
|
196
|
+
: data.statusPageUrl;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// The status page's logo, for the default email, or "" when it has none.
|
|
200
|
+
public static getLogoUrl(data: {
|
|
201
|
+
statusPage: StatusPage;
|
|
202
|
+
host: Hostname;
|
|
203
|
+
httpProtocol: Protocol;
|
|
204
|
+
}): string {
|
|
205
|
+
const statusPageId: string | null =
|
|
206
|
+
data.statusPage.id?.toString() || data.statusPage._id?.toString() || null;
|
|
207
|
+
|
|
208
|
+
return data.statusPage.logoFileId && statusPageId
|
|
209
|
+
? new URL(data.httpProtocol, data.host)
|
|
210
|
+
.addRoute(StatusPageApiRoute)
|
|
211
|
+
.addRoute(`/logo/${statusPageId}`)
|
|
212
|
+
.toString()
|
|
213
|
+
: "";
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/*
|
|
217
|
+
* Which email a page's subscribers get: its custom template only when the
|
|
218
|
+
* template has a body and the page sends through its own SMTP server.
|
|
219
|
+
*/
|
|
220
|
+
public static chooseTemplate(data: {
|
|
221
|
+
emailTemplate: StatusPageSubscriberNotificationTemplate | null;
|
|
222
|
+
statusPage: StatusPage;
|
|
223
|
+
}): SubscriberEmailTemplateChoice {
|
|
224
|
+
const customTemplateName: string | undefined =
|
|
225
|
+
data.emailTemplate?.templateName || undefined;
|
|
226
|
+
|
|
227
|
+
if (!data.emailTemplate) {
|
|
228
|
+
return {
|
|
229
|
+
usesCustomTemplate: false,
|
|
230
|
+
reason: SubscriberEmailTemplateChoiceReason.NoCustomTemplate,
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
if (!data.emailTemplate.templateBody) {
|
|
235
|
+
return {
|
|
236
|
+
usesCustomTemplate: false,
|
|
237
|
+
reason: SubscriberEmailTemplateChoiceReason.CustomTemplateIsEmpty,
|
|
238
|
+
customTemplateName: customTemplateName,
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
if (!data.statusPage.smtpConfig) {
|
|
243
|
+
return {
|
|
244
|
+
usesCustomTemplate: false,
|
|
245
|
+
reason:
|
|
246
|
+
SubscriberEmailTemplateChoiceReason.CustomTemplateNeedsCustomSmtp,
|
|
247
|
+
customTemplateName: customTemplateName,
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
return {
|
|
252
|
+
usesCustomTemplate: true,
|
|
253
|
+
reason: SubscriberEmailTemplateChoiceReason.CustomTemplate,
|
|
254
|
+
customTemplateName: customTemplateName,
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
/**
|
|
259
|
+
* One status page's email for this event. Looks up the page's custom
|
|
260
|
+
* email template for the event; everything else comes in: the values
|
|
261
|
+
* (buildTemplateVariables, then forStatusPage for this page), the page's
|
|
262
|
+
* URL and the incident's details URL on it (getDetailsUrl), and the
|
|
263
|
+
* instance's host and protocol for the logo.
|
|
264
|
+
*
|
|
265
|
+
* The page needs what StatusPageSubscriberService.
|
|
266
|
+
* getStatusPagesToSendNotification reads: its names, logoFileId,
|
|
267
|
+
* isPublicStatusPage, smtpConfig and the footer text columns.
|
|
268
|
+
*/
|
|
269
|
+
public static async forStatusPage(data: {
|
|
270
|
+
event: SubscriberIncidentEmailEvent;
|
|
271
|
+
incident: Incident;
|
|
272
|
+
incidentTemplateVariables: IncidentTemplateVariables;
|
|
273
|
+
statusPage: StatusPage;
|
|
274
|
+
statusPageUrl: string;
|
|
275
|
+
detailsUrl: string;
|
|
276
|
+
pageTemplateVariables: IncidentStatusPageTemplateVariables;
|
|
277
|
+
host: Hostname;
|
|
278
|
+
httpProtocol: Protocol;
|
|
279
|
+
}): Promise<SubscriberIncidentStatusPageEmail> {
|
|
280
|
+
const copy: SubscriberIncidentEmailCopy = EMAIL_COPY[data.event];
|
|
281
|
+
const statusPage: StatusPage = data.statusPage;
|
|
282
|
+
const incidentTemplateVariables: IncidentTemplateVariables =
|
|
283
|
+
data.incidentTemplateVariables;
|
|
284
|
+
const pageTemplateVariables: IncidentStatusPageTemplateVariables =
|
|
285
|
+
data.pageTemplateVariables;
|
|
286
|
+
const incidentTitle: string = data.incident.title || "";
|
|
287
|
+
|
|
288
|
+
if (!statusPage.id) {
|
|
289
|
+
throw new BadDataException(
|
|
290
|
+
"Cannot build a status page's subscriber email without its id.",
|
|
291
|
+
);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
const emailTemplate: StatusPageSubscriberNotificationTemplate | null =
|
|
295
|
+
await StatusPageSubscriberNotificationTemplateService.getTemplateForStatusPage(
|
|
296
|
+
{
|
|
297
|
+
statusPageId: statusPage.id,
|
|
298
|
+
eventType: copy.templateEventType,
|
|
299
|
+
notificationMethod: StatusPageSubscriberNotificationMethod.Email,
|
|
300
|
+
},
|
|
301
|
+
);
|
|
302
|
+
|
|
303
|
+
const templateChoice: SubscriberEmailTemplateChoice = this.chooseTemplate({
|
|
304
|
+
emailTemplate: emailTemplate,
|
|
305
|
+
statusPage: statusPage,
|
|
306
|
+
});
|
|
307
|
+
|
|
308
|
+
if (templateChoice.usesCustomTemplate) {
|
|
309
|
+
return {
|
|
310
|
+
templateChoice: templateChoice,
|
|
311
|
+
forSubscriber: (subscriber: {
|
|
312
|
+
unsubscribeUrl: string;
|
|
313
|
+
}): SubscriberIncidentEmail => {
|
|
314
|
+
/*
|
|
315
|
+
* The body is HTML (BlankTemplate wraps nothing around it), so its
|
|
316
|
+
* plain values are escaped; the subject is text, and gets them as
|
|
317
|
+
* written.
|
|
318
|
+
*/
|
|
319
|
+
const emailBodyTemplateVariables: SubscriberNotificationEmailBodyTemplateVariables =
|
|
320
|
+
{
|
|
321
|
+
...pageTemplateVariables.emailBody,
|
|
322
|
+
unsubscribeUrl: subscriber.unsubscribeUrl,
|
|
323
|
+
};
|
|
324
|
+
const plainTextTemplateVariables: Record<string, string> = {
|
|
325
|
+
...pageTemplateVariables.plainText,
|
|
326
|
+
unsubscribeUrl: subscriber.unsubscribeUrl,
|
|
327
|
+
};
|
|
328
|
+
|
|
329
|
+
const compiledBody: string =
|
|
330
|
+
StatusPageSubscriberNotificationTemplateServiceClass.compileEmailBodyTemplate(
|
|
331
|
+
emailTemplate!.templateBody!,
|
|
332
|
+
emailBodyTemplateVariables,
|
|
333
|
+
);
|
|
334
|
+
const compiledSubject: string = emailTemplate!.emailSubject
|
|
335
|
+
? StatusPageSubscriberNotificationTemplateServiceClass.compileTemplate(
|
|
336
|
+
emailTemplate!.emailSubject,
|
|
337
|
+
plainTextTemplateVariables,
|
|
338
|
+
)
|
|
339
|
+
: copy.customTemplateSubjectPrefix + incidentTitle;
|
|
340
|
+
|
|
341
|
+
return {
|
|
342
|
+
subject: compiledSubject,
|
|
343
|
+
envelope: {
|
|
344
|
+
templateType: EmailTemplateType.BlankTemplate,
|
|
345
|
+
vars: {
|
|
346
|
+
body: compiledBody,
|
|
347
|
+
},
|
|
348
|
+
subject: compiledSubject,
|
|
349
|
+
isSubjectLiteral: true,
|
|
350
|
+
},
|
|
351
|
+
};
|
|
352
|
+
},
|
|
353
|
+
recordSending: async (): Promise<void> => {
|
|
354
|
+
await incidentTemplateVariables.recordFieldsUsedBy([
|
|
355
|
+
emailTemplate!.templateBody,
|
|
356
|
+
emailTemplate!.emailSubject,
|
|
357
|
+
]);
|
|
358
|
+
},
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
const subject: string = copy.defaultSubjectPrefix + incidentTitle;
|
|
363
|
+
|
|
364
|
+
// What the default email reads that does not vary per subscriber.
|
|
365
|
+
const pageVars: JSONObject = {
|
|
366
|
+
statusPageName:
|
|
367
|
+
IncidentTemplateVariableBuilder.getStatusPageName(statusPage),
|
|
368
|
+
statusPageUrl: data.statusPageUrl,
|
|
369
|
+
detailsUrl: data.detailsUrl,
|
|
370
|
+
logoUrl: this.getLogoUrl({
|
|
371
|
+
statusPage: statusPage,
|
|
372
|
+
host: data.host,
|
|
373
|
+
httpProtocol: data.httpProtocol,
|
|
374
|
+
}),
|
|
375
|
+
isPublicStatusPage: statusPage.isPublicStatusPage ? "true" : "false",
|
|
376
|
+
// Every name escaped, "<br/>" between groups: for the raw slot.
|
|
377
|
+
resourcesAffected: pageTemplateVariables.resourcesAffectedHtml,
|
|
378
|
+
incidentSeverity: data.incident.incidentSeverity?.name || " - ",
|
|
379
|
+
incidentTitle: incidentTitle,
|
|
380
|
+
// The fields marked "Include in Subscriber Notifications".
|
|
381
|
+
customFieldRows:
|
|
382
|
+
pageTemplateVariables.customFieldRows as unknown as JSONObject,
|
|
383
|
+
subscriberEmailNotificationFooterText:
|
|
384
|
+
StatusPageServiceType.getSubscriberEmailFooterText(statusPage),
|
|
385
|
+
};
|
|
386
|
+
|
|
387
|
+
// The event's own content, rendered from Markdown once per send.
|
|
388
|
+
if (data.event === SubscriberIncidentEmailEvent.IncidentCreated) {
|
|
389
|
+
pageVars["incidentDescription"] =
|
|
390
|
+
incidentTemplateVariables.getMarkdownVariable(
|
|
391
|
+
"incidentDescription",
|
|
392
|
+
).html;
|
|
393
|
+
} else {
|
|
394
|
+
pageVars["note"] =
|
|
395
|
+
incidentTemplateVariables.getMarkdownVariable("note").html;
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
return {
|
|
399
|
+
templateChoice: templateChoice,
|
|
400
|
+
forSubscriber: (subscriber: {
|
|
401
|
+
unsubscribeUrl: string;
|
|
402
|
+
}): SubscriberIncidentEmail => {
|
|
403
|
+
return {
|
|
404
|
+
subject: subject,
|
|
405
|
+
envelope: {
|
|
406
|
+
templateType: copy.defaultTemplateType,
|
|
407
|
+
vars: {
|
|
408
|
+
...pageVars,
|
|
409
|
+
unsubscribeUrl: subscriber.unsubscribeUrl,
|
|
410
|
+
} as EmailEnvelope["vars"],
|
|
411
|
+
subject: subject,
|
|
412
|
+
isSubjectLiteral: true,
|
|
413
|
+
},
|
|
414
|
+
};
|
|
415
|
+
},
|
|
416
|
+
recordSending: async (): Promise<void> => {
|
|
417
|
+
await incidentTemplateVariables.recordIncludedFieldsSent();
|
|
418
|
+
},
|
|
419
|
+
};
|
|
420
|
+
}
|
|
421
|
+
}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import BaseModel from "../../../Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel";
|
|
2
|
+
import PartialEntity from "../../../Types/Database/PartialEntity";
|
|
3
|
+
import OneUptimeDate from "../../../Types/Date";
|
|
4
|
+
import ObjectID from "../../../Types/ObjectID";
|
|
5
|
+
import StatusPageSubscriberNotificationStatus from "../../../Types/StatusPage/StatusPageSubscriberNotificationStatus";
|
|
6
|
+
import DatabaseService from "../../Services/DatabaseService";
|
|
7
|
+
|
|
8
|
+
/*
|
|
9
|
+
* The two writes that move a subscriber notification in and out of
|
|
10
|
+
* InProgress without racing anyone: a job claiming a Pending notification to
|
|
11
|
+
* send it, and the sweeper failing one whose send was interrupted.
|
|
12
|
+
*
|
|
13
|
+
* Why a claim. The subscriber jobs run every minute, and a run can now take
|
|
14
|
+
* as long as its sends (SubscriberNotificationTiming), so the next run starts
|
|
15
|
+
* while the last is still going - on another worker slot, or another worker.
|
|
16
|
+
* Each run reads the Pending notifications when it starts. Without a claim,
|
|
17
|
+
* a run still working through its list would send a notification a later run
|
|
18
|
+
* had already sent, or pick up one that was re-queued since it read it and
|
|
19
|
+
* send it with what it read before (for the incident created notification,
|
|
20
|
+
* an old record of the pages already told, so those pages would be told
|
|
21
|
+
* again).
|
|
22
|
+
*
|
|
23
|
+
* A claim is one conditional UPDATE: Pending to InProgress, only if the row
|
|
24
|
+
* is still Pending and its version is still the one the job read. Every
|
|
25
|
+
* write through the services bumps the version, so a notification that was
|
|
26
|
+
* sent, re-queued or edited since is left for a run that reads it afresh.
|
|
27
|
+
* Exactly one run wins a notification. The claim is a hook-free write: it
|
|
28
|
+
* fires none of the row's 'on update' workflows, realtime events or audit
|
|
29
|
+
* log entries (the status the send settles on does). It stamps updatedAt,
|
|
30
|
+
* and, for a notification with one, its claimed-at column: the sweeper times
|
|
31
|
+
* an InProgress row from the claimed-at column where there is one, since
|
|
32
|
+
* other code writes those rows (an open incident or episode) all the time,
|
|
33
|
+
* and from updatedAt otherwise.
|
|
34
|
+
*/
|
|
35
|
+
export default class SubscriberNotificationClaim {
|
|
36
|
+
/*
|
|
37
|
+
* Claim a Pending notification for this run. True when this run is now the
|
|
38
|
+
* one sending it; false when it is no longer Pending, or changed since the
|
|
39
|
+
* job read it (another run has it, or will read it afresh).
|
|
40
|
+
*
|
|
41
|
+
* `version` is the row's version as the job read it. A row read without
|
|
42
|
+
* one is claimed on its status alone.
|
|
43
|
+
*
|
|
44
|
+
* `claimedAtColumn` is stamped with the time of the claim, for the
|
|
45
|
+
* sweeper (see Incident.subscriberNotificationClaimedAtOnIncidentCreated).
|
|
46
|
+
*
|
|
47
|
+
* `alsoSet` settles other columns of the row in the same write, only if
|
|
48
|
+
* they still hold `expected`: the public note jobs use it to skip a note's
|
|
49
|
+
* update notification that the 'posted' notification they are claiming
|
|
50
|
+
* already covers (see the note jobs).
|
|
51
|
+
*/
|
|
52
|
+
public static async claim<TBaseModel extends BaseModel>(data: {
|
|
53
|
+
service: DatabaseService<TBaseModel>;
|
|
54
|
+
id: ObjectID;
|
|
55
|
+
statusColumn: keyof TBaseModel & string;
|
|
56
|
+
version: number | undefined | null;
|
|
57
|
+
claimedAtColumn?: (keyof TBaseModel & string) | undefined;
|
|
58
|
+
alsoSet?:
|
|
59
|
+
| {
|
|
60
|
+
data: PartialEntity<TBaseModel>;
|
|
61
|
+
expected: PartialEntity<TBaseModel>;
|
|
62
|
+
}
|
|
63
|
+
| undefined;
|
|
64
|
+
}): Promise<boolean> {
|
|
65
|
+
return await data.service.compareAndSetColumnsByIdWithoutHooks({
|
|
66
|
+
id: data.id,
|
|
67
|
+
data: {
|
|
68
|
+
...(data.alsoSet?.data || {}),
|
|
69
|
+
[data.statusColumn]: StatusPageSubscriberNotificationStatus.InProgress,
|
|
70
|
+
...(data.claimedAtColumn
|
|
71
|
+
? { [data.claimedAtColumn]: OneUptimeDate.getCurrentDate() }
|
|
72
|
+
: {}),
|
|
73
|
+
} as unknown as PartialEntity<TBaseModel>,
|
|
74
|
+
expectedData: {
|
|
75
|
+
...(data.alsoSet?.expected || {}),
|
|
76
|
+
[data.statusColumn]: StatusPageSubscriberNotificationStatus.Pending,
|
|
77
|
+
...(typeof data.version === "number" ? { version: data.version } : {}),
|
|
78
|
+
} as unknown as PartialEntity<TBaseModel>,
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/*
|
|
83
|
+
* Fail a notification whose send was interrupted, with the reason, if it
|
|
84
|
+
* is still InProgress at the version the sweeper read. False when its send
|
|
85
|
+
* settled, or it was sent again, in the meantime.
|
|
86
|
+
*/
|
|
87
|
+
public static async failInterrupted<TBaseModel extends BaseModel>(data: {
|
|
88
|
+
service: DatabaseService<TBaseModel>;
|
|
89
|
+
id: ObjectID;
|
|
90
|
+
statusColumn: keyof TBaseModel & string;
|
|
91
|
+
messageColumn: keyof TBaseModel & string;
|
|
92
|
+
message: string;
|
|
93
|
+
version: number | undefined | null;
|
|
94
|
+
}): Promise<boolean> {
|
|
95
|
+
return await data.service.compareAndSetColumnsByIdWithoutHooks({
|
|
96
|
+
id: data.id,
|
|
97
|
+
data: {
|
|
98
|
+
[data.statusColumn]: StatusPageSubscriberNotificationStatus.Failed,
|
|
99
|
+
[data.messageColumn]: data.message,
|
|
100
|
+
} as unknown as PartialEntity<TBaseModel>,
|
|
101
|
+
expectedData: {
|
|
102
|
+
[data.statusColumn]: StatusPageSubscriberNotificationStatus.InProgress,
|
|
103
|
+
...(typeof data.version === "number" ? { version: data.version } : {}),
|
|
104
|
+
} as unknown as PartialEntity<TBaseModel>,
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
}
|