@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
|
@@ -362,6 +362,11 @@ describe("StatusPageAPI manage-subscription link recipient", () => {
|
|
|
362
362
|
.spyOn(StatusPageSubscriberService, "findBy")
|
|
363
363
|
.mockImplementation(findByFake as never);
|
|
364
364
|
|
|
365
|
+
// Their unsubscribe tokens are topped up in the database; nothing to top up here.
|
|
366
|
+
jest
|
|
367
|
+
.spyOn(StatusPageSubscriberService, "ensureUnsubscribeTokens")
|
|
368
|
+
.mockResolvedValue(undefined as never);
|
|
369
|
+
|
|
365
370
|
jest
|
|
366
371
|
.spyOn(StatusPageSubscriberService, "getStatusPagesToSendNotification")
|
|
367
372
|
.mockImplementation((): Promise<Array<StatusPage>> => {
|
|
@@ -610,8 +615,12 @@ describe("StatusPageAPI manage-subscription link recipient", () => {
|
|
|
610
615
|
expect(lookup.query["statusPageId"]?.toString()).toBe(
|
|
611
616
|
statusPageId.toString(),
|
|
612
617
|
);
|
|
618
|
+
/*
|
|
619
|
+
* The contact for this channel only, and the unsubscribe token for the
|
|
620
|
+
* link that works without signing in.
|
|
621
|
+
*/
|
|
613
622
|
expect(Object.keys(lookup.select).sort()).toEqual(
|
|
614
|
-
["_id", "subscriberPhone"].sort(),
|
|
623
|
+
["_id", "subscriberPhone", "unsubscribeToken"].sort(),
|
|
615
624
|
);
|
|
616
625
|
expect(lookup.sort).toEqual({ createdAt: SortOrder.Ascending });
|
|
617
626
|
expect(lookup.skip).toBe(0);
|
|
@@ -99,6 +99,27 @@ const STATUS_PAGE_URL: string = "https://status.acme-example.com";
|
|
|
99
99
|
const MANAGE_URL: string =
|
|
100
100
|
"https://status.acme-example.com/update-subscription/c47d2e19-5b8a-4e36-a0f2-7d91b3c56e28";
|
|
101
101
|
|
|
102
|
+
/*
|
|
103
|
+
* The subscription's unsubscribe token, and the link that works without
|
|
104
|
+
* signing in - which the manage page on a private status page does not.
|
|
105
|
+
*/
|
|
106
|
+
const UNSUBSCRIBE_TOKEN: string = "5d".repeat(32);
|
|
107
|
+
const UNSUBSCRIBE_URL: string = `https://status.acme-example.com/unsubscribe/c47d2e19-5b8a-4e36-a0f2-7d91b3c56e28-${UNSUBSCRIBE_TOKEN}`;
|
|
108
|
+
|
|
109
|
+
/*
|
|
110
|
+
* The unsubscribeUrl a channel's template is given. An SMS from a public
|
|
111
|
+
* status page gets the (shorter) manage link, as every other SMS from one
|
|
112
|
+
* does - an SMS is billed by the segment (see
|
|
113
|
+
* StatusPageSubscriberUnsubscribe.buildSmsLink); the fixture page is public.
|
|
114
|
+
*/
|
|
115
|
+
function unsubscribeUrlOnPublicPage(
|
|
116
|
+
method: StatusPageSubscriberNotificationMethod,
|
|
117
|
+
): string {
|
|
118
|
+
return method === StatusPageSubscriberNotificationMethod.SMS
|
|
119
|
+
? MANAGE_URL
|
|
120
|
+
: UNSUBSCRIBE_URL;
|
|
121
|
+
}
|
|
122
|
+
|
|
102
123
|
const SUBSCRIBER_EMAIL: string = "manage.subscriber@acme-example.com";
|
|
103
124
|
const SUBSCRIBER_PHONE: string = "+15550100123";
|
|
104
125
|
const SLACK_WORKSPACE_NAME: string = "acme-ops-workspace";
|
|
@@ -398,15 +419,45 @@ describe("StatusPageAPI manage-subscription templates", () => {
|
|
|
398
419
|
|
|
399
420
|
type CompileCallsFunction = () => Array<CompileCall>;
|
|
400
421
|
|
|
422
|
+
/*
|
|
423
|
+
* Every compile, in the order it was made: the email body through
|
|
424
|
+
* compileEmailBodyTemplate (it is HTML, so its values are escaped), and
|
|
425
|
+
* the subject, SMS, Slack and Teams through compileTemplate.
|
|
426
|
+
*/
|
|
401
427
|
const compileCalls: CompileCallsFunction = (): Array<CompileCall> => {
|
|
402
|
-
|
|
428
|
+
const recorded: Array<{ order: number; call: CompileCall }> = [];
|
|
429
|
+
|
|
430
|
+
for (const compile of [
|
|
403
431
|
StatusPageSubscriberNotificationTemplateServiceClass.compileTemplate,
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
432
|
+
StatusPageSubscriberNotificationTemplateServiceClass.compileEmailBodyTemplate,
|
|
433
|
+
]) {
|
|
434
|
+
const calls: jest.MockContext<unknown, Array<unknown>> = mockOf(
|
|
435
|
+
compile,
|
|
436
|
+
).mock;
|
|
437
|
+
|
|
438
|
+
calls.calls.forEach((call: Array<unknown>, index: number): void => {
|
|
439
|
+
recorded.push({
|
|
440
|
+
order: calls.invocationCallOrder[index]!,
|
|
441
|
+
call: {
|
|
442
|
+
template: call[0] as string,
|
|
443
|
+
variables: call[1] as Record<string, string>,
|
|
444
|
+
},
|
|
445
|
+
});
|
|
446
|
+
});
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
return recorded
|
|
450
|
+
.sort(
|
|
451
|
+
(
|
|
452
|
+
a: { order: number; call: CompileCall },
|
|
453
|
+
b: { order: number; call: CompileCall },
|
|
454
|
+
): number => {
|
|
455
|
+
return a.order - b.order;
|
|
456
|
+
},
|
|
457
|
+
)
|
|
458
|
+
.map((entry: { order: number; call: CompileCall }): CompileCall => {
|
|
459
|
+
return entry.call;
|
|
460
|
+
});
|
|
410
461
|
};
|
|
411
462
|
|
|
412
463
|
type SentMailFunction = () => Array<JSONObject>;
|
|
@@ -486,6 +537,7 @@ describe("StatusPageAPI manage-subscription templates", () => {
|
|
|
486
537
|
|
|
487
538
|
const subscriber: StatusPageSubscriber = new StatusPageSubscriber();
|
|
488
539
|
subscriber.id = new ObjectID(SUBSCRIBER_ID);
|
|
540
|
+
subscriber.unsubscribeToken = UNSUBSCRIBE_TOKEN;
|
|
489
541
|
|
|
490
542
|
if (query["subscriberEmail"]?.toString() === SUBSCRIBER_EMAIL) {
|
|
491
543
|
subscriber.subscriberEmail = new Email(SUBSCRIBER_EMAIL);
|
|
@@ -569,8 +621,9 @@ describe("StatusPageAPI manage-subscription templates", () => {
|
|
|
569
621
|
return Promise.resolve([pageToSend]);
|
|
570
622
|
});
|
|
571
623
|
|
|
572
|
-
// The real link
|
|
624
|
+
// The real link builders, watched.
|
|
573
625
|
jest.spyOn(StatusPageSubscriberService, "getUnsubscribeLink");
|
|
626
|
+
jest.spyOn(StatusPageSubscriberService, "getManageSubscriptionLink");
|
|
574
627
|
|
|
575
628
|
jest
|
|
576
629
|
.spyOn(
|
|
@@ -584,6 +637,10 @@ describe("StatusPageAPI manage-subscription templates", () => {
|
|
|
584
637
|
StatusPageSubscriberNotificationTemplateServiceClass,
|
|
585
638
|
"compileTemplate",
|
|
586
639
|
);
|
|
640
|
+
jest.spyOn(
|
|
641
|
+
StatusPageSubscriberNotificationTemplateServiceClass,
|
|
642
|
+
"compileEmailBodyTemplate",
|
|
643
|
+
);
|
|
587
644
|
|
|
588
645
|
jest.spyOn(MailService, "sendMail").mockResolvedValue(undefined as never);
|
|
589
646
|
jest.spyOn(SmsService, "sendSms").mockResolvedValue(undefined as never);
|
|
@@ -776,39 +833,134 @@ describe("StatusPageAPI manage-subscription templates", () => {
|
|
|
776
833
|
|
|
777
834
|
describe("variable values", () => {
|
|
778
835
|
it.each(CHANNELS)(
|
|
779
|
-
"$name:
|
|
836
|
+
"$name: manageSubscriptionUrl is the manage page and unsubscribeUrl the token link",
|
|
780
837
|
async (channel: ChannelCase) => {
|
|
781
838
|
useCustomTemplatesOnEveryChannel();
|
|
782
839
|
|
|
783
840
|
await callManageSubscription(channel.requestData);
|
|
784
841
|
|
|
785
|
-
// Built by the real
|
|
842
|
+
// Built by the real helpers from the page URL and this subscriber.
|
|
843
|
+
const manageCalls: Array<Array<unknown>> = mockOf(
|
|
844
|
+
StatusPageSubscriberService.getManageSubscriptionLink,
|
|
845
|
+
).mock.calls as Array<Array<unknown>>;
|
|
846
|
+
expect(manageCalls).toHaveLength(1);
|
|
847
|
+
expect((manageCalls[0]![0] as URL).toString()).toBe(
|
|
848
|
+
URL.fromString(STATUS_PAGE_URL).toString(),
|
|
849
|
+
);
|
|
850
|
+
expect((manageCalls[0]![1] as ObjectID).toString()).toBe(SUBSCRIBER_ID);
|
|
851
|
+
|
|
852
|
+
/*
|
|
853
|
+
* The unsubscribe link is built from the subscriber row the lookup
|
|
854
|
+
* read - token included - so it works without signing in.
|
|
855
|
+
*/
|
|
786
856
|
const linkCalls: Array<Array<unknown>> = mockOf(
|
|
787
857
|
StatusPageSubscriberService.getUnsubscribeLink,
|
|
788
858
|
).mock.calls as Array<Array<unknown>>;
|
|
789
859
|
expect(linkCalls).toHaveLength(1);
|
|
790
|
-
expect(
|
|
791
|
-
|
|
792
|
-
);
|
|
793
|
-
expect((linkCalls[0]![1] as ObjectID).toString()).toBe(SUBSCRIBER_ID);
|
|
860
|
+
expect(
|
|
861
|
+
(linkCalls[0]![1] as StatusPageSubscriber).unsubscribeToken,
|
|
862
|
+
).toBe(UNSUBSCRIBE_TOKEN);
|
|
794
863
|
|
|
795
|
-
expect(MANAGE_URL).not.toBe(STATUS_PAGE_URL);
|
|
796
864
|
expect(MANAGE_URL).toContain(SUBSCRIBER_ID);
|
|
865
|
+
expect(UNSUBSCRIBE_URL).toContain(UNSUBSCRIBE_TOKEN);
|
|
797
866
|
|
|
798
867
|
const calls: Array<CompileCall> = compileCalls();
|
|
799
868
|
expect(calls).toHaveLength(channel.compileCallsPerRequest);
|
|
800
869
|
for (const call of calls) {
|
|
801
|
-
expect(call.variables["unsubscribeUrl"]).toBe(
|
|
870
|
+
expect(call.variables["unsubscribeUrl"]).toBe(
|
|
871
|
+
unsubscribeUrlOnPublicPage(channel.method),
|
|
872
|
+
);
|
|
802
873
|
expect(call.variables["manageSubscriptionUrl"]).toBe(MANAGE_URL);
|
|
803
874
|
expect(call.variables["statusPageUrl"]).toBe(STATUS_PAGE_URL);
|
|
804
875
|
}
|
|
805
876
|
|
|
806
877
|
expect(renderedMessage(channel)).toContain(
|
|
807
|
-
`unsubscribeUrl=[${
|
|
878
|
+
`unsubscribeUrl=[${unsubscribeUrlOnPublicPage(channel.method)}]`,
|
|
808
879
|
);
|
|
809
880
|
},
|
|
810
881
|
);
|
|
811
882
|
|
|
883
|
+
it("sms from a private status page: unsubscribeUrl is the token link, since its manage page needs a signed-in visitor", async () => {
|
|
884
|
+
const smsChannel: ChannelCase = CHANNELS.find(
|
|
885
|
+
(channel: ChannelCase): boolean => {
|
|
886
|
+
return channel.method === StatusPageSubscriberNotificationMethod.SMS;
|
|
887
|
+
},
|
|
888
|
+
)!;
|
|
889
|
+
|
|
890
|
+
useCustomTemplatesOnEveryChannel();
|
|
891
|
+
pageToSend.isPublicStatusPage = false;
|
|
892
|
+
|
|
893
|
+
await callManageSubscription(smsChannel.requestData);
|
|
894
|
+
|
|
895
|
+
const calls: Array<CompileCall> = compileCalls();
|
|
896
|
+
expect(calls).toHaveLength(smsChannel.compileCallsPerRequest);
|
|
897
|
+
for (const call of calls) {
|
|
898
|
+
expect(call.variables["unsubscribeUrl"]).toBe(UNSUBSCRIBE_URL);
|
|
899
|
+
expect(call.variables["manageSubscriptionUrl"]).toBe(MANAGE_URL);
|
|
900
|
+
}
|
|
901
|
+
expect(renderedMessage(smsChannel)).toContain(
|
|
902
|
+
`unsubscribeUrl=[${UNSUBSCRIBE_URL}]`,
|
|
903
|
+
);
|
|
904
|
+
});
|
|
905
|
+
|
|
906
|
+
it("reads each subscriber's unsubscribe token with the lookup", async () => {
|
|
907
|
+
await callManageSubscription(CHANNELS[0]!.requestData);
|
|
908
|
+
|
|
909
|
+
const select: JSONObject = (
|
|
910
|
+
mockOf(StatusPageSubscriberService.findBy).mock.calls[0]![0] as {
|
|
911
|
+
select: JSONObject;
|
|
912
|
+
}
|
|
913
|
+
).select;
|
|
914
|
+
|
|
915
|
+
expect(select["unsubscribeToken"]).toBe(true);
|
|
916
|
+
});
|
|
917
|
+
|
|
918
|
+
/*
|
|
919
|
+
* Every other sender tops up a missing token before building the link
|
|
920
|
+
* (ensureUnsubscribeTokens); a subscriber the backfill has not reached
|
|
921
|
+
* yet would otherwise be sent a link to the "out of date" page.
|
|
922
|
+
*/
|
|
923
|
+
it("a subscriber read without its token is given one before the link is built", async () => {
|
|
924
|
+
const toppedUpToken: string = "9c".repeat(32);
|
|
925
|
+
|
|
926
|
+
jest
|
|
927
|
+
.spyOn(StatusPageSubscriberService, "findBy")
|
|
928
|
+
.mockImplementation((async (findBy: { query: JSONObject }) => {
|
|
929
|
+
const found: Array<StatusPageSubscriber> =
|
|
930
|
+
await findSubscribersFake(findBy);
|
|
931
|
+
|
|
932
|
+
for (const subscriber of found) {
|
|
933
|
+
subscriber.unsubscribeToken = undefined as unknown as string;
|
|
934
|
+
}
|
|
935
|
+
|
|
936
|
+
return found;
|
|
937
|
+
}) as never);
|
|
938
|
+
|
|
939
|
+
const ensure: jest.SpyInstance = jest
|
|
940
|
+
.spyOn(StatusPageSubscriberService, "ensureUnsubscribeTokens")
|
|
941
|
+
.mockImplementation((async (
|
|
942
|
+
subscribers: Array<StatusPageSubscriber>,
|
|
943
|
+
): Promise<void> => {
|
|
944
|
+
for (const subscriber of subscribers) {
|
|
945
|
+
subscriber.unsubscribeToken = toppedUpToken;
|
|
946
|
+
}
|
|
947
|
+
}) as never);
|
|
948
|
+
|
|
949
|
+
useCustomTemplatesOnEveryChannel();
|
|
950
|
+
|
|
951
|
+
await callManageSubscription(CHANNELS[0]!.requestData);
|
|
952
|
+
|
|
953
|
+
expect(ensure).toHaveBeenCalledTimes(1);
|
|
954
|
+
|
|
955
|
+
const calls: Array<CompileCall> = compileCalls();
|
|
956
|
+
expect(calls.length).toBeGreaterThan(0);
|
|
957
|
+
for (const call of calls) {
|
|
958
|
+
expect(call.variables["unsubscribeUrl"]).toBe(
|
|
959
|
+
`${STATUS_PAGE_URL}/unsubscribe/${SUBSCRIBER_ID}-${toppedUpToken}`,
|
|
960
|
+
);
|
|
961
|
+
}
|
|
962
|
+
});
|
|
963
|
+
|
|
812
964
|
it.each(CHANNELS)(
|
|
813
965
|
"$name: statusPageName is the page's public title, not its internal name",
|
|
814
966
|
async (channel: ChannelCase) => {
|
|
@@ -834,6 +986,42 @@ describe("StatusPageAPI manage-subscription templates", () => {
|
|
|
834
986
|
},
|
|
835
987
|
);
|
|
836
988
|
|
|
989
|
+
/*
|
|
990
|
+
* The email body is HTML, so the page's title - which a project member
|
|
991
|
+
* typed - is escaped into it and cannot add markup. SMS, Slack and Teams
|
|
992
|
+
* show text as written, and the subject is plain text, so they get it
|
|
993
|
+
* unchanged.
|
|
994
|
+
*/
|
|
995
|
+
it.each(CHANNELS)(
|
|
996
|
+
"$name: a page title holding markup is escaped only in the email body",
|
|
997
|
+
async (channel: ChannelCase) => {
|
|
998
|
+
const hostileTitle: string =
|
|
999
|
+
'<a href="https://evil.example/login">Acme</a> & "Co"';
|
|
1000
|
+
useCustomTemplatesOnEveryChannel();
|
|
1001
|
+
pageToSend = statusPageFixture({
|
|
1002
|
+
withCustomSmtpAndSms: true,
|
|
1003
|
+
pageTitle: hostileTitle,
|
|
1004
|
+
});
|
|
1005
|
+
|
|
1006
|
+
await callManageSubscription(channel.requestData);
|
|
1007
|
+
|
|
1008
|
+
const message: string = renderedMessage(channel);
|
|
1009
|
+
|
|
1010
|
+
if (channel.method === StatusPageSubscriberNotificationMethod.Email) {
|
|
1011
|
+
expect(message).toContain(
|
|
1012
|
+
"statusPageName=[<a href="https://evil.example/login">Acme</a> & "Co"]",
|
|
1013
|
+
);
|
|
1014
|
+
expect(message).not.toContain("<a href");
|
|
1015
|
+
expect(sentMail()[0]!["subject"]).toBe(
|
|
1016
|
+
`Manage ${hostileTitle} at ${MANAGE_URL}`,
|
|
1017
|
+
);
|
|
1018
|
+
} else {
|
|
1019
|
+
expect(message).toContain(`statusPageName=[${hostileTitle}]`);
|
|
1020
|
+
expect(message).not.toMatch(/&(?:amp|lt|gt|quot|#39);/);
|
|
1021
|
+
}
|
|
1022
|
+
},
|
|
1023
|
+
);
|
|
1024
|
+
|
|
837
1025
|
interface NameFallbackCase {
|
|
838
1026
|
channel: ChannelCase;
|
|
839
1027
|
label: string;
|
|
@@ -901,7 +1089,7 @@ describe("StatusPageAPI manage-subscription templates", () => {
|
|
|
901
1089
|
const expectedValues: Record<string, string> = {
|
|
902
1090
|
statusPageName: PAGE_TITLE,
|
|
903
1091
|
statusPageUrl: STATUS_PAGE_URL,
|
|
904
|
-
unsubscribeUrl:
|
|
1092
|
+
unsubscribeUrl: unsubscribeUrlOnPublicPage(channel.method),
|
|
905
1093
|
manageSubscriptionUrl: MANAGE_URL,
|
|
906
1094
|
};
|
|
907
1095
|
|
|
@@ -86,6 +86,7 @@ function mockServices(data: { overview: boolean }): Fixtures {
|
|
|
86
86
|
page.projectId = ObjectID.generate();
|
|
87
87
|
page.isPublicStatusPage = true;
|
|
88
88
|
page.showIncidentsOnStatusPage = true;
|
|
89
|
+
page.onlyShowScopedIncidents = false;
|
|
89
90
|
|
|
90
91
|
const resource: StatusPageResource = new StatusPageResource();
|
|
91
92
|
resource._id = ObjectID.generate().toString();
|
|
@@ -223,6 +224,15 @@ function mockServices(data: { overview: boolean }): Fixtures {
|
|
|
223
224
|
return Promise.resolve([]);
|
|
224
225
|
}
|
|
225
226
|
|
|
227
|
+
/*
|
|
228
|
+
* Each read is asked in two halves (IncidentStatusPageScope): incidents
|
|
229
|
+
* limited to no status page, which these all are, and incidents limited
|
|
230
|
+
* to this page, of which there are none.
|
|
231
|
+
*/
|
|
232
|
+
if (query["isScopedToStatusPages"] !== false) {
|
|
233
|
+
return Promise.resolve([]);
|
|
234
|
+
}
|
|
235
|
+
|
|
226
236
|
if (query["_id"]) {
|
|
227
237
|
return Promise.resolve(
|
|
228
238
|
incidents.filter((incident: Incident) => {
|
|
@@ -406,7 +416,8 @@ describe("StatusPageAPI postmortem visibility", () => {
|
|
|
406
416
|
statusPageId: fixtures.statusPageId,
|
|
407
417
|
});
|
|
408
418
|
|
|
409
|
-
|
|
419
|
+
// Recent and active incidents, each read in two halves.
|
|
420
|
+
expect(fixtures.incidentReadSpy).toHaveBeenCalledTimes(2 * 2);
|
|
410
421
|
expectVisibility({
|
|
411
422
|
payload,
|
|
412
423
|
key: "incidents",
|
|
@@ -433,7 +444,8 @@ describe("StatusPageAPI postmortem visibility", () => {
|
|
|
433
444
|
incidentId: incident._id!,
|
|
434
445
|
});
|
|
435
446
|
|
|
436
|
-
|
|
447
|
+
// The one incident, read in two halves.
|
|
448
|
+
expect(fixtures.incidentReadSpy).toHaveBeenCalledTimes(2);
|
|
437
449
|
expectVisibility({ payload, key: "incidents", incidents: [incident] });
|
|
438
450
|
expectSourcesUnchanged(fixtures);
|
|
439
451
|
},
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
import StatusPageSubscriber from "../../../Models/DatabaseModels/StatusPageSubscriber";
|
|
2
|
+
import BaseModel from "../../../Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel";
|
|
3
|
+
import BaseAPI from "../../../Server/API/BaseAPI";
|
|
4
|
+
import DatabaseService from "../../../Server/Services/DatabaseService";
|
|
5
|
+
import ProjectService from "../../../Server/Services/ProjectService";
|
|
6
|
+
import StatusPageSubscriberService, {
|
|
7
|
+
Service as StatusPageSubscriberServiceClass,
|
|
8
|
+
} from "../../../Server/Services/StatusPageSubscriberService";
|
|
9
|
+
import {
|
|
10
|
+
RunOptions,
|
|
11
|
+
RunReturnType,
|
|
12
|
+
} from "../../../Server/Types/Workflow/ComponentCode";
|
|
13
|
+
import CreateManyBaseModel from "../../../Server/Types/Workflow/Components/BaseModel/CreateManyBaseModel";
|
|
14
|
+
import CreateOneBaseModel from "../../../Server/Types/Workflow/Components/BaseModel/CreateOneBaseModel";
|
|
15
|
+
import {
|
|
16
|
+
ExpressResponse,
|
|
17
|
+
OneUptimeRequest,
|
|
18
|
+
} from "../../../Server/Utils/Express";
|
|
19
|
+
import Response from "../../../Server/Utils/Response";
|
|
20
|
+
import Email from "../../../Types/Email";
|
|
21
|
+
import Exception from "../../../Types/Exception/Exception";
|
|
22
|
+
import { JSONArray, JSONObject } from "../../../Types/JSON";
|
|
23
|
+
import ObjectID from "../../../Types/ObjectID";
|
|
24
|
+
import UserType from "../../../Types/UserType";
|
|
25
|
+
import { mockRouter } from "./Helpers";
|
|
26
|
+
import {
|
|
27
|
+
afterEach,
|
|
28
|
+
beforeEach,
|
|
29
|
+
describe,
|
|
30
|
+
expect,
|
|
31
|
+
jest,
|
|
32
|
+
test,
|
|
33
|
+
} from "@jest/globals";
|
|
34
|
+
|
|
35
|
+
jest.mock("../../../Server/Utils/Express", () => {
|
|
36
|
+
return {
|
|
37
|
+
getRouter: () => {
|
|
38
|
+
return mockRouter;
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
jest.mock("../../../Server/Utils/Response", () => {
|
|
44
|
+
return {
|
|
45
|
+
sendEmptySuccessResponse: jest.fn(),
|
|
46
|
+
sendEntityResponse: jest.fn(),
|
|
47
|
+
sendEntityArrayResponse: jest.fn(),
|
|
48
|
+
sendJsonObjectResponse: jest.fn(),
|
|
49
|
+
};
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
/*
|
|
53
|
+
* A subscriber's create hands back the row it saved, and the unsubscribe
|
|
54
|
+
* token and the confirmation code are on that row: StatusPageSubscriberService
|
|
55
|
+
* minted them in onBeforeCreate. Nobody may read either column (read: []), but
|
|
56
|
+
* the create response of POST /status-page-subscriber is serialized whole,
|
|
57
|
+
* without a column read check - so a teammate's Add Subscriber or Add in Bulk,
|
|
58
|
+
* or any API key, got the token back, and could cancel the subscription
|
|
59
|
+
* "through the link", which the team's notice then blamed on the subscriber.
|
|
60
|
+
* A workflow's Create Status Page Subscriber step returned it too, and step
|
|
61
|
+
* return values are kept in the workflow's logs.
|
|
62
|
+
*
|
|
63
|
+
* DatabaseService.create is replaced with one that returns the saved row as
|
|
64
|
+
* the real one does, secrets and all; the service's own create is real.
|
|
65
|
+
*/
|
|
66
|
+
|
|
67
|
+
const PROJECT_ID: ObjectID = new ObjectID(
|
|
68
|
+
"10000000-0000-4000-8000-000000000001",
|
|
69
|
+
);
|
|
70
|
+
const STATUS_PAGE_ID: ObjectID = new ObjectID(
|
|
71
|
+
"20000000-0000-4000-8000-000000000002",
|
|
72
|
+
);
|
|
73
|
+
const SUBSCRIBER_ID: string = "30000000-0000-4000-8000-000000000003";
|
|
74
|
+
const TOKEN: string = "4d".repeat(32);
|
|
75
|
+
const CONFIRMATION_CODE: string = "654321";
|
|
76
|
+
|
|
77
|
+
function savedRow(): StatusPageSubscriber {
|
|
78
|
+
const row: StatusPageSubscriber = new StatusPageSubscriber();
|
|
79
|
+
row._id = SUBSCRIBER_ID;
|
|
80
|
+
row.projectId = PROJECT_ID;
|
|
81
|
+
row.statusPageId = STATUS_PAGE_ID;
|
|
82
|
+
row.subscriberEmail = new Email("site03-all@acme.com");
|
|
83
|
+
row.isSubscriptionConfirmed = true;
|
|
84
|
+
row.isAddedByTeam = true;
|
|
85
|
+
row.unsubscribeToken = TOKEN;
|
|
86
|
+
row.subscriptionConfirmationToken = CONFIRMATION_CODE;
|
|
87
|
+
return row;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function expectNoSecrets(json: JSONObject): void {
|
|
91
|
+
const text: string = JSON.stringify(json);
|
|
92
|
+
|
|
93
|
+
expect(json["unsubscribeToken"]).toBeUndefined();
|
|
94
|
+
expect(json["subscriptionConfirmationToken"]).toBeUndefined();
|
|
95
|
+
expect(text).not.toContain(TOKEN);
|
|
96
|
+
expect(text).not.toContain(CONFIRMATION_CODE);
|
|
97
|
+
|
|
98
|
+
// The rest of the row is still there.
|
|
99
|
+
expect(json["_id"]).toBe(SUBSCRIBER_ID);
|
|
100
|
+
expect(JSON.stringify(json["subscriberEmail"])).toContain(
|
|
101
|
+
"site03-all@acme.com",
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
beforeEach(() => {
|
|
106
|
+
// With billing on, the request's props carry the project's plan.
|
|
107
|
+
jest
|
|
108
|
+
.spyOn(ProjectService, "getCurrentPlan")
|
|
109
|
+
.mockResolvedValue({ plan: null, isSubscriptionUnpaid: false } as never);
|
|
110
|
+
|
|
111
|
+
jest.spyOn(DatabaseService.prototype, "create").mockImplementation((() => {
|
|
112
|
+
return Promise.resolve(savedRow());
|
|
113
|
+
}) as never);
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
afterEach(() => {
|
|
117
|
+
jest.restoreAllMocks();
|
|
118
|
+
jest.clearAllMocks();
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
describe("POST /status-page-subscriber answers without the subscriber's secrets", () => {
|
|
122
|
+
function request(userType: UserType): OneUptimeRequest {
|
|
123
|
+
return {
|
|
124
|
+
params: {},
|
|
125
|
+
headers: {},
|
|
126
|
+
userType: userType,
|
|
127
|
+
tenantId: PROJECT_ID,
|
|
128
|
+
body: {
|
|
129
|
+
data: {
|
|
130
|
+
statusPageId: STATUS_PAGE_ID.toString(),
|
|
131
|
+
subscriberEmail: "site03-all@acme.com",
|
|
132
|
+
},
|
|
133
|
+
},
|
|
134
|
+
} as unknown as OneUptimeRequest;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
test.each([
|
|
138
|
+
["a teammate's Add Subscriber or Add in Bulk", UserType.User],
|
|
139
|
+
["an API key", UserType.API],
|
|
140
|
+
])("%s", async (_label: string, userType: UserType) => {
|
|
141
|
+
const api: BaseAPI<StatusPageSubscriber, StatusPageSubscriberServiceClass> =
|
|
142
|
+
new BaseAPI<StatusPageSubscriber, StatusPageSubscriberServiceClass>(
|
|
143
|
+
StatusPageSubscriber,
|
|
144
|
+
StatusPageSubscriberService,
|
|
145
|
+
);
|
|
146
|
+
|
|
147
|
+
await api.createItem(request(userType), {} as ExpressResponse);
|
|
148
|
+
|
|
149
|
+
const sendEntityResponse: jest.Mock =
|
|
150
|
+
Response.sendEntityResponse as unknown as jest.Mock;
|
|
151
|
+
expect(sendEntityResponse).toHaveBeenCalledTimes(1);
|
|
152
|
+
|
|
153
|
+
const item: StatusPageSubscriber = sendEntityResponse.mock
|
|
154
|
+
.calls[0]![2] as StatusPageSubscriber;
|
|
155
|
+
|
|
156
|
+
// What Response.sendEntityResponse serializes: every column that is set.
|
|
157
|
+
expectNoSecrets(BaseModel.toJSON(item, StatusPageSubscriber));
|
|
158
|
+
});
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
describe("a workflow's create steps return the subscriber without its secrets", () => {
|
|
162
|
+
function options(): RunOptions {
|
|
163
|
+
return {
|
|
164
|
+
log: jest.fn() as unknown as RunOptions["log"],
|
|
165
|
+
workflowLogId: ObjectID.generate(),
|
|
166
|
+
workflowId: ObjectID.generate(),
|
|
167
|
+
projectId: PROJECT_ID,
|
|
168
|
+
onError: ((exception: Exception): Exception => {
|
|
169
|
+
return exception;
|
|
170
|
+
}) as RunOptions["onError"],
|
|
171
|
+
executeWorkflow: async (): Promise<void> => {},
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
test("Create Status Page Subscriber", async () => {
|
|
176
|
+
const component: CreateOneBaseModel<StatusPageSubscriber> =
|
|
177
|
+
new CreateOneBaseModel<StatusPageSubscriber>(StatusPageSubscriberService);
|
|
178
|
+
|
|
179
|
+
const result: RunReturnType = await component.run(
|
|
180
|
+
{
|
|
181
|
+
json: {
|
|
182
|
+
statusPageId: STATUS_PAGE_ID.toString(),
|
|
183
|
+
subscriberEmail: "site03-all@acme.com",
|
|
184
|
+
},
|
|
185
|
+
},
|
|
186
|
+
options(),
|
|
187
|
+
);
|
|
188
|
+
|
|
189
|
+
expect(result.executePort?.id).toBe("success");
|
|
190
|
+
expectNoSecrets(result.returnValues["model"] as JSONObject);
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
test("Create Many Status Page Subscribers", async () => {
|
|
194
|
+
const component: CreateManyBaseModel<StatusPageSubscriber> =
|
|
195
|
+
new CreateManyBaseModel<StatusPageSubscriber>(
|
|
196
|
+
StatusPageSubscriberService,
|
|
197
|
+
);
|
|
198
|
+
|
|
199
|
+
const result: RunReturnType = await component.run(
|
|
200
|
+
{
|
|
201
|
+
"json-array": [
|
|
202
|
+
{
|
|
203
|
+
statusPageId: STATUS_PAGE_ID.toString(),
|
|
204
|
+
subscriberEmail: "site03-all@acme.com",
|
|
205
|
+
},
|
|
206
|
+
],
|
|
207
|
+
},
|
|
208
|
+
options(),
|
|
209
|
+
);
|
|
210
|
+
|
|
211
|
+
expect(result.executePort?.id).toBe("success");
|
|
212
|
+
|
|
213
|
+
const models: JSONArray = result.returnValues["models"] as JSONArray;
|
|
214
|
+
expect(models).toHaveLength(1);
|
|
215
|
+
expectNoSecrets(models[0] as JSONObject);
|
|
216
|
+
});
|
|
217
|
+
});
|