@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,656 @@
|
|
|
1
|
+
import Incident from "../../../Models/DatabaseModels/Incident";
|
|
2
|
+
import Monitor from "../../../Models/DatabaseModels/Monitor";
|
|
3
|
+
import StatusPage from "../../../Models/DatabaseModels/StatusPage";
|
|
4
|
+
import DatabaseCommonInteractionProps from "../../../Types/BaseDatabase/DatabaseCommonInteractionProps";
|
|
5
|
+
import DatabaseCommonInteractionPropsUtil, {
|
|
6
|
+
PermissionType,
|
|
7
|
+
} from "../../../Types/BaseDatabase/DatabaseCommonInteractionPropsUtil";
|
|
8
|
+
import Permission, { UserPermission } from "../../../Types/Permission";
|
|
9
|
+
import { LIMIT_PER_PROJECT } from "../../../Types/Database/LimitMax";
|
|
10
|
+
import Dictionary from "../../../Types/Dictionary";
|
|
11
|
+
import BadDataException from "../../../Types/Exception/BadDataException";
|
|
12
|
+
import NotAuthorizedException from "../../../Types/Exception/NotAuthorizedException";
|
|
13
|
+
import NotFoundException from "../../../Types/Exception/NotFoundException";
|
|
14
|
+
import ObjectID from "../../../Types/ObjectID";
|
|
15
|
+
import IncidentScopeAddedPagesNotification from "../../../Types/StatusPage/IncidentScopeAddedPagesNotification";
|
|
16
|
+
import IncidentSubscriberAudience, {
|
|
17
|
+
IncidentSubscriberAudienceCounts,
|
|
18
|
+
IncidentSubscriberAudienceExcludedStatusPage,
|
|
19
|
+
IncidentSubscriberAudienceExclusionReason,
|
|
20
|
+
IncidentSubscriberAudienceNamedStatusPage,
|
|
21
|
+
IncidentSubscriberAudienceResult,
|
|
22
|
+
IncidentSubscriberAudienceStatusPage,
|
|
23
|
+
} from "../../../Types/StatusPage/IncidentSubscriberAudience";
|
|
24
|
+
import IncidentService from "../../Services/IncidentService";
|
|
25
|
+
import MonitorService from "../../Services/MonitorService";
|
|
26
|
+
import StatusPageService from "../../Services/StatusPageService";
|
|
27
|
+
import StatusPageSubscriberService from "../../Services/StatusPageSubscriberService";
|
|
28
|
+
import QueryHelper from "../../Types/Database/QueryHelper";
|
|
29
|
+
import IncidentStatusPageScope, {
|
|
30
|
+
ExcludedStatusPage,
|
|
31
|
+
ResolvedIncidentStatusPages,
|
|
32
|
+
StatusPageExclusionReason,
|
|
33
|
+
} from "./IncidentStatusPageScope";
|
|
34
|
+
|
|
35
|
+
/*
|
|
36
|
+
* Who an incident's status page notifications would reach (see
|
|
37
|
+
* Common/Types/StatusPage/IncidentSubscriberAudience), for
|
|
38
|
+
* POST /incident/subscriber-audience.
|
|
39
|
+
*
|
|
40
|
+
* Which pages an incident reaches is IncidentStatusPageScope's call, the same
|
|
41
|
+
* as for the subscriber jobs: through its monitors, narrowed to the pages it
|
|
42
|
+
* is limited to, without the pages that only show scoped incidents when it is
|
|
43
|
+
* not scoped. On top of that, a page that does not show incidents at all is
|
|
44
|
+
* skipped by the jobs, so it is reported as left out here too.
|
|
45
|
+
*
|
|
46
|
+
* What the caller learns is bounded by what they may read:
|
|
47
|
+
*
|
|
48
|
+
* - the incident is read with the caller's own permissions (labels, private
|
|
49
|
+
* incidents), and must be in the caller's project;
|
|
50
|
+
* - monitors and status pages named for an incident being declared must be
|
|
51
|
+
* the project's; another project's id is refused, not looked up;
|
|
52
|
+
* - a status page the caller cannot read (status pages are label-scoped, and
|
|
53
|
+
* incident roles do not read them at all) is not named here and its
|
|
54
|
+
* subscribers are not counted - the pages that will be notified that the
|
|
55
|
+
* caller cannot see come back as one number;
|
|
56
|
+
* - subscribers are counted, never read out. No address leaves the server.
|
|
57
|
+
*
|
|
58
|
+
* What that protects is which pages list an incident's monitors, looking
|
|
59
|
+
* ahead: this summary (and the notification preview built on it) is open to
|
|
60
|
+
* anyone who may declare an incident or post a note, before anything is
|
|
61
|
+
* sent. The pages an incident is limited to are part of the incident, like
|
|
62
|
+
* its monitors and like a scheduled maintenance event's status pages: anyone
|
|
63
|
+
* who can read the incident sees their names (the Status Page Scope card,
|
|
64
|
+
* and the incident feed, which names the pages added to and removed from
|
|
65
|
+
* the scope), whether or not they can read those status pages themselves.
|
|
66
|
+
*
|
|
67
|
+
* So is what a send reached, once it has gone out: the notification's
|
|
68
|
+
* status message and its feed item name every page it went to, with what
|
|
69
|
+
* was sent and failed on each (SubscriberNotificationDeliveryRecord), and
|
|
70
|
+
* everyone who can read the incident - or the note - reads them. That is
|
|
71
|
+
* the record of what the incident told whom, which is its purpose; the docs
|
|
72
|
+
* say so (One Status Page per Audience, Permissions). Only the look-ahead
|
|
73
|
+
* here keeps to the pages the caller can read.
|
|
74
|
+
*/
|
|
75
|
+
|
|
76
|
+
export type IncidentSubscriberAudienceRequest =
|
|
77
|
+
| {
|
|
78
|
+
projectId: ObjectID;
|
|
79
|
+
props: DatabaseCommonInteractionProps;
|
|
80
|
+
incidentId: ObjectID;
|
|
81
|
+
/*
|
|
82
|
+
* Who a Retry of the incident's 'created' notification reaches: the
|
|
83
|
+
* pages it was already sent to in full (its record,
|
|
84
|
+
* Incident.statusPagesNotifiedOnCreation) are not sent it again, so
|
|
85
|
+
* they are reported as left out, with why, rather than as notified.
|
|
86
|
+
*/
|
|
87
|
+
excludeStatusPagesNotifiedOnCreation?: boolean | undefined;
|
|
88
|
+
}
|
|
89
|
+
| {
|
|
90
|
+
projectId: ObjectID;
|
|
91
|
+
props: DatabaseCommonInteractionProps;
|
|
92
|
+
monitorIds: Array<ObjectID>;
|
|
93
|
+
statusPageIds: Array<ObjectID>;
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
/*
|
|
97
|
+
* The audience with the status pages behind it, for a caller that goes on to
|
|
98
|
+
* build what those pages are sent (the notification preview): the pages the
|
|
99
|
+
* incident reaches, as the subscriber jobs load them, and the resources each
|
|
100
|
+
* lists. Never serialized: it holds every page, readable or not, and each
|
|
101
|
+
* page's mail and SMS settings.
|
|
102
|
+
*/
|
|
103
|
+
export interface IncidentSubscriberAudienceWithStatusPages {
|
|
104
|
+
audience: IncidentSubscriberAudienceResult;
|
|
105
|
+
resolved: ResolvedIncidentStatusPages;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// What decides the audience, once the request is resolved.
|
|
109
|
+
interface AudienceInputs {
|
|
110
|
+
resolved: ResolvedIncidentStatusPages;
|
|
111
|
+
hasMonitors: boolean;
|
|
112
|
+
// The pages the incident is limited to, lower-cased; empty when unscoped.
|
|
113
|
+
scopedStatusPageIds: Array<string>;
|
|
114
|
+
isHiddenFromStatusPages: boolean;
|
|
115
|
+
/*
|
|
116
|
+
* The pages a Retry of the 'created' notification skips, lower-cased;
|
|
117
|
+
* empty unless the request asked (excludeStatusPagesNotifiedOnCreation).
|
|
118
|
+
*/
|
|
119
|
+
alreadyNotifiedStatusPageIds: Array<string>;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
export default class IncidentSubscriberAudienceBuilder {
|
|
123
|
+
/*
|
|
124
|
+
* The roles that may see who an incident's notifications would reach, and
|
|
125
|
+
* preview what they would be sent: the ones that may declare an incident,
|
|
126
|
+
* edit one, or post a public note on one - the places the audience is
|
|
127
|
+
* shown. Which incident, monitors and status pages an answer covers is
|
|
128
|
+
* then bounded by what the caller may read.
|
|
129
|
+
*/
|
|
130
|
+
public static readonly PERMISSIONS: ReadonlyArray<Permission> = [
|
|
131
|
+
Permission.ProjectOwner,
|
|
132
|
+
Permission.ProjectAdmin,
|
|
133
|
+
Permission.ProjectMember,
|
|
134
|
+
Permission.IncidentAdmin,
|
|
135
|
+
Permission.IncidentMember,
|
|
136
|
+
Permission.CreateProjectIncident,
|
|
137
|
+
Permission.EditProjectIncident,
|
|
138
|
+
Permission.CreateIncidentPublicNote,
|
|
139
|
+
];
|
|
140
|
+
|
|
141
|
+
/*
|
|
142
|
+
* Refuses a caller who holds none of PERMISSIONS in the project. Read
|
|
143
|
+
* through getUserPermissions(Allow): the tenant permission list holds
|
|
144
|
+
* grants and denials together, and a team's block entry for one of these
|
|
145
|
+
* must not count as a grant of it.
|
|
146
|
+
*/
|
|
147
|
+
public static assertCallerMaySeeAudience(
|
|
148
|
+
props: DatabaseCommonInteractionProps,
|
|
149
|
+
): void {
|
|
150
|
+
if (props.isMasterAdmin) {
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
const permissions: Array<Permission> =
|
|
155
|
+
DatabaseCommonInteractionPropsUtil.getUserPermissions(
|
|
156
|
+
props,
|
|
157
|
+
PermissionType.Allow,
|
|
158
|
+
).map((userPermission: UserPermission) => {
|
|
159
|
+
return userPermission.permission;
|
|
160
|
+
});
|
|
161
|
+
|
|
162
|
+
const hasPermission: boolean = permissions.some((p: Permission) => {
|
|
163
|
+
return this.PERMISSIONS.includes(p);
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
if (!hasPermission) {
|
|
167
|
+
throw new NotAuthorizedException(
|
|
168
|
+
"You do not have permission to see who this incident's status page notifications would reach. You need one of these permissions: Project Owner, Project Admin, Project Member, Incident Admin, Incident Member, Create Incident, Edit Incident, Create Incident Public Note.",
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
public static async build(
|
|
174
|
+
request: IncidentSubscriberAudienceRequest,
|
|
175
|
+
): Promise<IncidentSubscriberAudienceResult> {
|
|
176
|
+
return (await this.buildWithStatusPages(request)).audience;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// The audience, and the status pages it was worked out from.
|
|
180
|
+
public static async buildWithStatusPages(
|
|
181
|
+
request: IncidentSubscriberAudienceRequest,
|
|
182
|
+
): Promise<IncidentSubscriberAudienceWithStatusPages> {
|
|
183
|
+
const inputs: AudienceInputs =
|
|
184
|
+
"incidentId" in request
|
|
185
|
+
? await this.getInputsForIncident(request)
|
|
186
|
+
: await this.getInputsForDraft(request);
|
|
187
|
+
|
|
188
|
+
const audience: IncidentSubscriberAudienceResult = await this.buildAudience(
|
|
189
|
+
{
|
|
190
|
+
projectId: request.projectId,
|
|
191
|
+
props: request.props,
|
|
192
|
+
inputs: inputs,
|
|
193
|
+
},
|
|
194
|
+
);
|
|
195
|
+
|
|
196
|
+
return {
|
|
197
|
+
audience: audience,
|
|
198
|
+
resolved: inputs.resolved,
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// An incident that exists: read with the caller's permissions.
|
|
203
|
+
private static async getInputsForIncident(request: {
|
|
204
|
+
projectId: ObjectID;
|
|
205
|
+
props: DatabaseCommonInteractionProps;
|
|
206
|
+
incidentId: ObjectID;
|
|
207
|
+
excludeStatusPagesNotifiedOnCreation?: boolean | undefined;
|
|
208
|
+
}): Promise<AudienceInputs> {
|
|
209
|
+
const incident: Incident | null = await IncidentService.findOneBy({
|
|
210
|
+
query: {
|
|
211
|
+
_id: request.incidentId,
|
|
212
|
+
projectId: request.projectId,
|
|
213
|
+
},
|
|
214
|
+
select: {
|
|
215
|
+
_id: true,
|
|
216
|
+
isVisibleOnStatusPage: true,
|
|
217
|
+
isPrivate: true,
|
|
218
|
+
monitors: {
|
|
219
|
+
_id: true,
|
|
220
|
+
},
|
|
221
|
+
},
|
|
222
|
+
props: request.props,
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
if (!incident) {
|
|
226
|
+
throw new NotFoundException("Incident not found");
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/*
|
|
230
|
+
* The scope is read as root, now that the caller has been shown to read
|
|
231
|
+
* the incident: its status page ids only decide which pages below are
|
|
232
|
+
* reported as listing none of its monitors, and those are named only if
|
|
233
|
+
* the caller can read them. The record of pages already sent the
|
|
234
|
+
* 'created' notification is read the same way, for a Retry's audience:
|
|
235
|
+
* it only moves pages from notified to left out.
|
|
236
|
+
*/
|
|
237
|
+
const incidentWithScope: Incident | null = await IncidentService.findOneBy({
|
|
238
|
+
query: {
|
|
239
|
+
_id: request.incidentId,
|
|
240
|
+
projectId: request.projectId,
|
|
241
|
+
},
|
|
242
|
+
select: {
|
|
243
|
+
_id: true,
|
|
244
|
+
isScopedToStatusPages: true,
|
|
245
|
+
statusPages: {
|
|
246
|
+
_id: true,
|
|
247
|
+
},
|
|
248
|
+
...(request.excludeStatusPagesNotifiedOnCreation
|
|
249
|
+
? { statusPagesNotifiedOnCreation: true }
|
|
250
|
+
: {}),
|
|
251
|
+
},
|
|
252
|
+
props: {
|
|
253
|
+
isRoot: true,
|
|
254
|
+
},
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
const resolved: ResolvedIncidentStatusPages =
|
|
258
|
+
await IncidentStatusPageScope.resolvePagesForIncidents({
|
|
259
|
+
incidents: [incident],
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
return {
|
|
263
|
+
resolved: resolved,
|
|
264
|
+
hasMonitors: (incident.monitors || []).length > 0,
|
|
265
|
+
scopedStatusPageIds:
|
|
266
|
+
incidentWithScope?.isScopedToStatusPages === true
|
|
267
|
+
? this.normalizeIds(incidentWithScope.statusPages)
|
|
268
|
+
: [],
|
|
269
|
+
/*
|
|
270
|
+
* The jobs send nothing for an incident hidden from status pages.
|
|
271
|
+
* Private incidents are always hidden (IncidentService forces it), but
|
|
272
|
+
* a row that says private is treated as hidden either way.
|
|
273
|
+
*/
|
|
274
|
+
isHiddenFromStatusPages:
|
|
275
|
+
incident.isVisibleOnStatusPage !== true || incident.isPrivate === true,
|
|
276
|
+
alreadyNotifiedStatusPageIds: request.excludeStatusPagesNotifiedOnCreation
|
|
277
|
+
? IncidentScopeAddedPagesNotification.normalizeStatusPageIds(
|
|
278
|
+
incidentWithScope?.statusPagesNotifiedOnCreation,
|
|
279
|
+
)
|
|
280
|
+
: [],
|
|
281
|
+
};
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/*
|
|
285
|
+
* An incident being declared: the monitors and status pages picked on the
|
|
286
|
+
* form. Both lists must be the project's.
|
|
287
|
+
*/
|
|
288
|
+
private static async getInputsForDraft(request: {
|
|
289
|
+
projectId: ObjectID;
|
|
290
|
+
props: DatabaseCommonInteractionProps;
|
|
291
|
+
monitorIds: Array<ObjectID>;
|
|
292
|
+
statusPageIds: Array<ObjectID>;
|
|
293
|
+
}): Promise<AudienceInputs> {
|
|
294
|
+
const monitorIds: Array<string> = this.normalizeIds(request.monitorIds);
|
|
295
|
+
const statusPageIds: Array<string> = this.normalizeIds(
|
|
296
|
+
request.statusPageIds,
|
|
297
|
+
);
|
|
298
|
+
|
|
299
|
+
await Promise.all([
|
|
300
|
+
this.assertBelongToProject({
|
|
301
|
+
ids: monitorIds,
|
|
302
|
+
projectId: request.projectId,
|
|
303
|
+
find: async (ids: Array<string>): Promise<Array<{ _id?: string }>> => {
|
|
304
|
+
return MonitorService.findBy({
|
|
305
|
+
query: {
|
|
306
|
+
_id: QueryHelper.any(ids),
|
|
307
|
+
projectId: request.projectId,
|
|
308
|
+
},
|
|
309
|
+
select: {
|
|
310
|
+
_id: true,
|
|
311
|
+
},
|
|
312
|
+
limit: ids.length,
|
|
313
|
+
skip: 0,
|
|
314
|
+
props: {
|
|
315
|
+
isRoot: true,
|
|
316
|
+
},
|
|
317
|
+
});
|
|
318
|
+
},
|
|
319
|
+
message:
|
|
320
|
+
"One or more of these monitors were not found in this project.",
|
|
321
|
+
}),
|
|
322
|
+
this.assertBelongToProject({
|
|
323
|
+
ids: statusPageIds,
|
|
324
|
+
projectId: request.projectId,
|
|
325
|
+
find: async (ids: Array<string>): Promise<Array<{ _id?: string }>> => {
|
|
326
|
+
return StatusPageService.findBy({
|
|
327
|
+
query: {
|
|
328
|
+
_id: QueryHelper.any(ids),
|
|
329
|
+
projectId: request.projectId,
|
|
330
|
+
},
|
|
331
|
+
select: {
|
|
332
|
+
_id: true,
|
|
333
|
+
},
|
|
334
|
+
limit: ids.length,
|
|
335
|
+
skip: 0,
|
|
336
|
+
props: {
|
|
337
|
+
isRoot: true,
|
|
338
|
+
},
|
|
339
|
+
});
|
|
340
|
+
},
|
|
341
|
+
message:
|
|
342
|
+
"One or more of these status pages were not found in this project.",
|
|
343
|
+
}),
|
|
344
|
+
]);
|
|
345
|
+
|
|
346
|
+
const resolved: ResolvedIncidentStatusPages =
|
|
347
|
+
await IncidentStatusPageScope.resolvePagesForDraftIncident({
|
|
348
|
+
monitorIds: monitorIds.map((id: string): ObjectID => {
|
|
349
|
+
return new ObjectID(id);
|
|
350
|
+
}),
|
|
351
|
+
statusPageIds: statusPageIds,
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
return {
|
|
355
|
+
resolved: resolved,
|
|
356
|
+
hasMonitors: monitorIds.length > 0,
|
|
357
|
+
scopedStatusPageIds: statusPageIds,
|
|
358
|
+
// The form knows whether the incident will be private; the page says so.
|
|
359
|
+
isHiddenFromStatusPages: false,
|
|
360
|
+
// Nothing has been sent about an incident not yet declared.
|
|
361
|
+
alreadyNotifiedStatusPageIds: [],
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
private static async assertBelongToProject(data: {
|
|
366
|
+
ids: Array<string>;
|
|
367
|
+
projectId: ObjectID;
|
|
368
|
+
find: (ids: Array<string>) => Promise<Array<{ _id?: string }>>;
|
|
369
|
+
message: string;
|
|
370
|
+
}): Promise<void> {
|
|
371
|
+
if (data.ids.length === 0) {
|
|
372
|
+
return;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
const found: Array<string> = this.normalizeIds(await data.find(data.ids));
|
|
376
|
+
|
|
377
|
+
const isEveryIdFound: boolean = data.ids.every((id: string): boolean => {
|
|
378
|
+
return found.includes(id);
|
|
379
|
+
});
|
|
380
|
+
|
|
381
|
+
if (!isEveryIdFound) {
|
|
382
|
+
throw new BadDataException(data.message);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
private static async buildAudience(data: {
|
|
387
|
+
projectId: ObjectID;
|
|
388
|
+
props: DatabaseCommonInteractionProps;
|
|
389
|
+
inputs: AudienceInputs;
|
|
390
|
+
}): Promise<IncidentSubscriberAudienceResult> {
|
|
391
|
+
const projectId: string = data.projectId.toString().toLowerCase();
|
|
392
|
+
|
|
393
|
+
// Another project's page cannot be reached; if one were, it is not told.
|
|
394
|
+
const isProjectPage: (statusPage: StatusPage) => boolean = (
|
|
395
|
+
statusPage: StatusPage,
|
|
396
|
+
): boolean => {
|
|
397
|
+
return (
|
|
398
|
+
!statusPage.projectId ||
|
|
399
|
+
statusPage.projectId.toString().toLowerCase() === projectId
|
|
400
|
+
);
|
|
401
|
+
};
|
|
402
|
+
|
|
403
|
+
const notifiedPages: Array<StatusPage> = [];
|
|
404
|
+
const excludedPages: Array<{
|
|
405
|
+
statusPage: StatusPage;
|
|
406
|
+
reason: IncidentSubscriberAudienceExclusionReason;
|
|
407
|
+
}> = [];
|
|
408
|
+
|
|
409
|
+
for (const statusPage of data.inputs.resolved.statusPages) {
|
|
410
|
+
if (!isProjectPage(statusPage)) {
|
|
411
|
+
continue;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
// The jobs skip a page that does not show incidents.
|
|
415
|
+
if (statusPage.showIncidentsOnStatusPage === false) {
|
|
416
|
+
excludedPages.push({
|
|
417
|
+
statusPage: statusPage,
|
|
418
|
+
reason: IncidentSubscriberAudienceExclusionReason.HidesIncidents,
|
|
419
|
+
});
|
|
420
|
+
continue;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
// A Retry of the 'created' notification resumes after these.
|
|
424
|
+
if (
|
|
425
|
+
data.inputs.alreadyNotifiedStatusPageIds.includes(
|
|
426
|
+
this.getId(statusPage),
|
|
427
|
+
)
|
|
428
|
+
) {
|
|
429
|
+
excludedPages.push({
|
|
430
|
+
statusPage: statusPage,
|
|
431
|
+
reason: IncidentSubscriberAudienceExclusionReason.AlreadyNotified,
|
|
432
|
+
});
|
|
433
|
+
continue;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
notifiedPages.push(statusPage);
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
for (const excluded of data.inputs.resolved.excludedStatusPages) {
|
|
440
|
+
if (!isProjectPage(excluded.statusPage)) {
|
|
441
|
+
continue;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
excludedPages.push({
|
|
445
|
+
statusPage: excluded.statusPage,
|
|
446
|
+
reason: this.toExclusionReason(excluded),
|
|
447
|
+
});
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
excludedPages.sort(
|
|
451
|
+
(
|
|
452
|
+
a: { statusPage: StatusPage },
|
|
453
|
+
b: { statusPage: StatusPage },
|
|
454
|
+
): number => {
|
|
455
|
+
return IncidentStatusPageScope.compareStatusPagesByName(
|
|
456
|
+
a.statusPage,
|
|
457
|
+
b.statusPage,
|
|
458
|
+
);
|
|
459
|
+
},
|
|
460
|
+
);
|
|
461
|
+
|
|
462
|
+
const reachedIds: Array<string> = [
|
|
463
|
+
...notifiedPages,
|
|
464
|
+
...excludedPages.map((excluded: { statusPage: StatusPage }) => {
|
|
465
|
+
return excluded.statusPage;
|
|
466
|
+
}),
|
|
467
|
+
]
|
|
468
|
+
.map((statusPage: StatusPage): string => {
|
|
469
|
+
return this.getId(statusPage);
|
|
470
|
+
})
|
|
471
|
+
.filter((id: string): boolean => {
|
|
472
|
+
return Boolean(id);
|
|
473
|
+
});
|
|
474
|
+
|
|
475
|
+
/*
|
|
476
|
+
* Pages the incident is limited to that its monitors do not reach. With
|
|
477
|
+
* no monitor at all nothing is reached, which the summary says on its
|
|
478
|
+
* own, so they are not listed then.
|
|
479
|
+
*/
|
|
480
|
+
const selectedNotListingMonitorIds: Array<string> = data.inputs.hasMonitors
|
|
481
|
+
? data.inputs.scopedStatusPageIds.filter((id: string): boolean => {
|
|
482
|
+
return !reachedIds.includes(id);
|
|
483
|
+
})
|
|
484
|
+
: [];
|
|
485
|
+
|
|
486
|
+
const readableNames: Dictionary<string> = await this.getReadableNames({
|
|
487
|
+
projectId: data.projectId,
|
|
488
|
+
props: data.props,
|
|
489
|
+
statusPageIds: [...reachedIds, ...selectedNotListingMonitorIds],
|
|
490
|
+
});
|
|
491
|
+
|
|
492
|
+
const isReadable: (id: string) => boolean = (id: string): boolean => {
|
|
493
|
+
return Object.prototype.hasOwnProperty.call(readableNames, id);
|
|
494
|
+
};
|
|
495
|
+
|
|
496
|
+
const readableNotifiedPages: Array<StatusPage> = notifiedPages.filter(
|
|
497
|
+
(statusPage: StatusPage): boolean => {
|
|
498
|
+
return isReadable(this.getId(statusPage));
|
|
499
|
+
},
|
|
500
|
+
);
|
|
501
|
+
|
|
502
|
+
const counts: Dictionary<IncidentSubscriberAudienceCounts> =
|
|
503
|
+
readableNotifiedPages.length > 0
|
|
504
|
+
? await StatusPageSubscriberService.countActiveSubscribersByChannel({
|
|
505
|
+
projectId: data.projectId,
|
|
506
|
+
statusPageIds: readableNotifiedPages.map(
|
|
507
|
+
(statusPage: StatusPage): ObjectID => {
|
|
508
|
+
return new ObjectID(this.getId(statusPage));
|
|
509
|
+
},
|
|
510
|
+
),
|
|
511
|
+
})
|
|
512
|
+
: {};
|
|
513
|
+
|
|
514
|
+
const statusPages: Array<IncidentSubscriberAudienceStatusPage> =
|
|
515
|
+
readableNotifiedPages.map(
|
|
516
|
+
(statusPage: StatusPage): IncidentSubscriberAudienceStatusPage => {
|
|
517
|
+
const id: string = this.getId(statusPage);
|
|
518
|
+
|
|
519
|
+
return {
|
|
520
|
+
statusPageId: id,
|
|
521
|
+
name: readableNames[id] || "",
|
|
522
|
+
subscriberCounts: {
|
|
523
|
+
...(counts[id] || IncidentSubscriberAudience.getEmptyCounts()),
|
|
524
|
+
},
|
|
525
|
+
};
|
|
526
|
+
},
|
|
527
|
+
);
|
|
528
|
+
|
|
529
|
+
const excludedStatusPages: Array<IncidentSubscriberAudienceExcludedStatusPage> =
|
|
530
|
+
excludedPages
|
|
531
|
+
.filter((excluded: { statusPage: StatusPage }): boolean => {
|
|
532
|
+
return isReadable(this.getId(excluded.statusPage));
|
|
533
|
+
})
|
|
534
|
+
.map(
|
|
535
|
+
(excluded: {
|
|
536
|
+
statusPage: StatusPage;
|
|
537
|
+
reason: IncidentSubscriberAudienceExclusionReason;
|
|
538
|
+
}): IncidentSubscriberAudienceExcludedStatusPage => {
|
|
539
|
+
const id: string = this.getId(excluded.statusPage);
|
|
540
|
+
|
|
541
|
+
return {
|
|
542
|
+
statusPageId: id,
|
|
543
|
+
name: readableNames[id] || "",
|
|
544
|
+
reason: excluded.reason,
|
|
545
|
+
};
|
|
546
|
+
},
|
|
547
|
+
);
|
|
548
|
+
|
|
549
|
+
const selectedStatusPagesNotListingMonitors: Array<IncidentSubscriberAudienceNamedStatusPage> =
|
|
550
|
+
selectedNotListingMonitorIds
|
|
551
|
+
.filter(isReadable)
|
|
552
|
+
.map((id: string): IncidentSubscriberAudienceNamedStatusPage => {
|
|
553
|
+
return {
|
|
554
|
+
statusPageId: id,
|
|
555
|
+
name: readableNames[id] || "",
|
|
556
|
+
};
|
|
557
|
+
})
|
|
558
|
+
.sort(
|
|
559
|
+
(
|
|
560
|
+
a: IncidentSubscriberAudienceNamedStatusPage,
|
|
561
|
+
b: IncidentSubscriberAudienceNamedStatusPage,
|
|
562
|
+
): number => {
|
|
563
|
+
return a.name.localeCompare(b.name, "en", {
|
|
564
|
+
sensitivity: "base",
|
|
565
|
+
numeric: true,
|
|
566
|
+
});
|
|
567
|
+
},
|
|
568
|
+
);
|
|
569
|
+
|
|
570
|
+
return {
|
|
571
|
+
hasMonitors: data.inputs.hasMonitors,
|
|
572
|
+
isScoped: data.inputs.resolved.isScoped,
|
|
573
|
+
isHiddenFromStatusPages: data.inputs.isHiddenFromStatusPages,
|
|
574
|
+
statusPages: statusPages,
|
|
575
|
+
hiddenStatusPageCount: notifiedPages.length - statusPages.length,
|
|
576
|
+
excludedStatusPages: excludedStatusPages,
|
|
577
|
+
selectedStatusPagesNotListingMonitors:
|
|
578
|
+
selectedStatusPagesNotListingMonitors,
|
|
579
|
+
};
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
/*
|
|
583
|
+
* The names of the status pages the caller may read, keyed by lower-cased
|
|
584
|
+
* id, read with the caller's own permissions - and so through the labels
|
|
585
|
+
* status page access is restricted by. A caller with no status page read
|
|
586
|
+
* access at all can read none of them.
|
|
587
|
+
*/
|
|
588
|
+
private static async getReadableNames(data: {
|
|
589
|
+
projectId: ObjectID;
|
|
590
|
+
props: DatabaseCommonInteractionProps;
|
|
591
|
+
statusPageIds: Array<string>;
|
|
592
|
+
}): Promise<Dictionary<string>> {
|
|
593
|
+
const names: Dictionary<string> = {};
|
|
594
|
+
|
|
595
|
+
const statusPageIds: Array<string> = this.normalizeIds(data.statusPageIds);
|
|
596
|
+
|
|
597
|
+
if (statusPageIds.length === 0) {
|
|
598
|
+
return names;
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
let statusPages: Array<StatusPage> = [];
|
|
602
|
+
|
|
603
|
+
try {
|
|
604
|
+
statusPages = await StatusPageService.findBy({
|
|
605
|
+
query: {
|
|
606
|
+
_id: QueryHelper.any(statusPageIds),
|
|
607
|
+
projectId: data.projectId,
|
|
608
|
+
},
|
|
609
|
+
select: {
|
|
610
|
+
_id: true,
|
|
611
|
+
name: true,
|
|
612
|
+
},
|
|
613
|
+
limit: Math.min(statusPageIds.length, LIMIT_PER_PROJECT),
|
|
614
|
+
skip: 0,
|
|
615
|
+
props: data.props,
|
|
616
|
+
});
|
|
617
|
+
} catch (err) {
|
|
618
|
+
if (err instanceof NotAuthorizedException) {
|
|
619
|
+
return names;
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
throw err;
|
|
623
|
+
}
|
|
624
|
+
|
|
625
|
+
for (const statusPage of statusPages) {
|
|
626
|
+
const id: string = this.getId(statusPage);
|
|
627
|
+
|
|
628
|
+
if (id && statusPageIds.includes(id)) {
|
|
629
|
+
names[id] = statusPage.name?.trim() || "Untitled status page";
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
return names;
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
private static toExclusionReason(
|
|
637
|
+
excluded: ExcludedStatusPage,
|
|
638
|
+
): IncidentSubscriberAudienceExclusionReason {
|
|
639
|
+
return excluded.reason ===
|
|
640
|
+
StatusPageExclusionReason.OnlyShowsScopedIncidents
|
|
641
|
+
? IncidentSubscriberAudienceExclusionReason.OnlyShowsScopedIncidents
|
|
642
|
+
: IncidentSubscriberAudienceExclusionReason.OutsideIncidentScope;
|
|
643
|
+
}
|
|
644
|
+
|
|
645
|
+
private static getId(model: StatusPage | Monitor): string {
|
|
646
|
+
return (model._id || model.id?.toString() || "").toString().toLowerCase();
|
|
647
|
+
}
|
|
648
|
+
|
|
649
|
+
/*
|
|
650
|
+
* Ids in any shape they arrive in - an ObjectID, a string, a model or a
|
|
651
|
+
* {_id} - lower-cased as the database returns them, without duplicates.
|
|
652
|
+
*/
|
|
653
|
+
private static normalizeIds(value: unknown): Array<string> {
|
|
654
|
+
return IncidentScopeAddedPagesNotification.normalizeStatusPageIds(value);
|
|
655
|
+
}
|
|
656
|
+
}
|