@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,311 @@
|
|
|
1
|
+
import Incident from "../../../Models/DatabaseModels/Incident";
|
|
2
|
+
import IncidentCustomField from "../../../Models/DatabaseModels/IncidentCustomField";
|
|
3
|
+
import IncidentState from "../../../Models/DatabaseModels/IncidentState";
|
|
4
|
+
import IncidentTemplate from "../../../Models/DatabaseModels/IncidentTemplate";
|
|
5
|
+
import CustomFieldMappingService from "../../../Server/Services/CustomFieldMappingService";
|
|
6
|
+
import IncidentCustomFieldService from "../../../Server/Services/IncidentCustomFieldService";
|
|
7
|
+
import IncidentService from "../../../Server/Services/IncidentService";
|
|
8
|
+
import IncidentStateService from "../../../Server/Services/IncidentStateService";
|
|
9
|
+
import IncidentTemplateService from "../../../Server/Services/IncidentTemplateService";
|
|
10
|
+
import ProjectService from "../../../Server/Services/ProjectService";
|
|
11
|
+
import UserService from "../../../Server/Services/UserService";
|
|
12
|
+
import CreateBy from "../../../Server/Types/Database/CreateBy";
|
|
13
|
+
import { OnCreate } from "../../../Server/Types/Database/Hooks";
|
|
14
|
+
import ProjectScopedReferenceValidator from "../../../Server/Utils/Database/ProjectScopedReferenceValidator";
|
|
15
|
+
import DatabaseCommonInteractionProps from "../../../Types/BaseDatabase/DatabaseCommonInteractionProps";
|
|
16
|
+
import CustomFieldType from "../../../Types/CustomField/CustomFieldType";
|
|
17
|
+
import { JSONObject } from "../../../Types/JSON";
|
|
18
|
+
import ObjectID from "../../../Types/ObjectID";
|
|
19
|
+
import getJestMockFunction, { MockFunction } from "../../MockType";
|
|
20
|
+
import {
|
|
21
|
+
afterEach,
|
|
22
|
+
beforeEach,
|
|
23
|
+
describe,
|
|
24
|
+
expect,
|
|
25
|
+
jest,
|
|
26
|
+
test,
|
|
27
|
+
} from "@jest/globals";
|
|
28
|
+
|
|
29
|
+
/*
|
|
30
|
+
* An incident created with `createdIncidentTemplateId` (API callers that send
|
|
31
|
+
* only the template, and the root paths that declare from one) copies the
|
|
32
|
+
* template's custom field values - a MERGE into what the incident is given:
|
|
33
|
+
*
|
|
34
|
+
* - the template fills in the fields the incident leaves out;
|
|
35
|
+
* - a value the incident sets wins, 0, false and null included;
|
|
36
|
+
* - the template's values are not checked as the caller's (the check sees
|
|
37
|
+
* only what the caller sent), so a stale template value never refuses
|
|
38
|
+
* the incident;
|
|
39
|
+
* - the mapping from monitors still runs after the copy, and wins for a
|
|
40
|
+
* mapped field.
|
|
41
|
+
*/
|
|
42
|
+
|
|
43
|
+
const projectId: ObjectID = new ObjectID(
|
|
44
|
+
"11111111-1111-4111-8111-111111111111",
|
|
45
|
+
);
|
|
46
|
+
const templateId: string = "a1b2c3d4-0000-4000-8000-0000000000aa";
|
|
47
|
+
|
|
48
|
+
const MEMBER_PROPS: DatabaseCommonInteractionProps = {
|
|
49
|
+
tenantId: projectId,
|
|
50
|
+
userId: new ObjectID("44444444-4444-4444-8444-444444444444"),
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
type OnBeforeCreate = (
|
|
54
|
+
createBy: CreateBy<Incident>,
|
|
55
|
+
) => Promise<OnCreate<Incident>>;
|
|
56
|
+
|
|
57
|
+
function definition(
|
|
58
|
+
name: string,
|
|
59
|
+
customFieldType: CustomFieldType,
|
|
60
|
+
dropdownOptions?: string,
|
|
61
|
+
): IncidentCustomField {
|
|
62
|
+
const field: IncidentCustomField = new IncidentCustomField();
|
|
63
|
+
field.name = name;
|
|
64
|
+
field.customFieldType = customFieldType;
|
|
65
|
+
|
|
66
|
+
if (dropdownOptions) {
|
|
67
|
+
field.dropdownOptions = dropdownOptions;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
return field;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
let template: IncidentTemplate | null = null;
|
|
74
|
+
let templateFindOneBy: MockFunction;
|
|
75
|
+
let definitionFindBy: MockFunction;
|
|
76
|
+
let applyMappingsToCreate: MockFunction;
|
|
77
|
+
|
|
78
|
+
function templateWith(customFields: unknown): IncidentTemplate {
|
|
79
|
+
const incidentTemplate: IncidentTemplate = new IncidentTemplate();
|
|
80
|
+
incidentTemplate._id = templateId;
|
|
81
|
+
incidentTemplate.customFields = customFields as JSONObject;
|
|
82
|
+
return incidentTemplate;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function newIncident(customFields?: unknown): Incident {
|
|
86
|
+
const incident: Incident = new Incident();
|
|
87
|
+
incident.title = "Site outage";
|
|
88
|
+
incident.incidentSeverityId = new ObjectID(
|
|
89
|
+
"d0000000-0000-4000-8000-000000000001",
|
|
90
|
+
);
|
|
91
|
+
incident.createdIncidentTemplateId = templateId;
|
|
92
|
+
|
|
93
|
+
if (customFields !== undefined) {
|
|
94
|
+
incident.customFields = customFields as JSONObject;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return incident;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
async function runBeforeCreate(
|
|
101
|
+
data: Incident,
|
|
102
|
+
props: DatabaseCommonInteractionProps = MEMBER_PROPS,
|
|
103
|
+
): Promise<Incident> {
|
|
104
|
+
const onCreate: OnCreate<Incident> = await (
|
|
105
|
+
IncidentService as unknown as { onBeforeCreate: OnBeforeCreate }
|
|
106
|
+
).onBeforeCreate({ data, props });
|
|
107
|
+
|
|
108
|
+
return onCreate.createBy.data;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
beforeEach(() => {
|
|
112
|
+
template = null;
|
|
113
|
+
|
|
114
|
+
const createdState: IncidentState = new IncidentState();
|
|
115
|
+
createdState._id = "c0000000-0000-4000-8000-000000000001";
|
|
116
|
+
jest
|
|
117
|
+
.spyOn(IncidentStateService, "findOneBy")
|
|
118
|
+
.mockResolvedValue(createdState as never);
|
|
119
|
+
jest
|
|
120
|
+
.spyOn(ProjectService, "incrementAndGetIncidentCounter")
|
|
121
|
+
.mockResolvedValue({ counter: 7, prefix: undefined } as never);
|
|
122
|
+
jest
|
|
123
|
+
.spyOn(ProjectScopedReferenceValidator, "validateReferencesBelongToProject")
|
|
124
|
+
.mockResolvedValue(undefined as never);
|
|
125
|
+
jest
|
|
126
|
+
.spyOn(UserService, "getUserMarkdownString")
|
|
127
|
+
.mockResolvedValue("Test User" as never);
|
|
128
|
+
|
|
129
|
+
templateFindOneBy = getJestMockFunction();
|
|
130
|
+
templateFindOneBy.mockImplementation(() => {
|
|
131
|
+
return Promise.resolve(template);
|
|
132
|
+
});
|
|
133
|
+
jest
|
|
134
|
+
.spyOn(IncidentTemplateService, "findOneBy")
|
|
135
|
+
.mockImplementation(templateFindOneBy as never);
|
|
136
|
+
|
|
137
|
+
definitionFindBy = getJestMockFunction();
|
|
138
|
+
definitionFindBy.mockResolvedValue([
|
|
139
|
+
definition("Impact", CustomFieldType.Dropdown, "Low\nMedium\nHigh"),
|
|
140
|
+
definition("Estimated Duration", CustomFieldType.Number),
|
|
141
|
+
definition("Acknowledgement", CustomFieldType.Boolean),
|
|
142
|
+
] as never);
|
|
143
|
+
jest
|
|
144
|
+
.spyOn(IncidentCustomFieldService, "findBy")
|
|
145
|
+
.mockImplementation(definitionFindBy as never);
|
|
146
|
+
|
|
147
|
+
applyMappingsToCreate = getJestMockFunction();
|
|
148
|
+
applyMappingsToCreate.mockResolvedValue(undefined as never);
|
|
149
|
+
jest
|
|
150
|
+
.spyOn(CustomFieldMappingService, "applyMappingsToCreate")
|
|
151
|
+
.mockImplementation(applyMappingsToCreate as never);
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
afterEach(() => {
|
|
155
|
+
jest.restoreAllMocks();
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
describe("IncidentService.onBeforeCreate: a template's custom field values", () => {
|
|
159
|
+
test("are read with the template, as root and within the project", async () => {
|
|
160
|
+
template = templateWith({ Impact: "High" });
|
|
161
|
+
|
|
162
|
+
await runBeforeCreate(newIncident());
|
|
163
|
+
|
|
164
|
+
const findOneBy: {
|
|
165
|
+
query: JSONObject;
|
|
166
|
+
select: JSONObject;
|
|
167
|
+
props: DatabaseCommonInteractionProps;
|
|
168
|
+
} = templateFindOneBy.mock.calls[0]![0] as {
|
|
169
|
+
query: JSONObject;
|
|
170
|
+
select: JSONObject;
|
|
171
|
+
props: DatabaseCommonInteractionProps;
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
expect(findOneBy.select["customFields"]).toBe(true);
|
|
175
|
+
expect(findOneBy.query["projectId"]).toBe(projectId);
|
|
176
|
+
expect(findOneBy.query["_id"]).toBe(templateId);
|
|
177
|
+
expect(findOneBy.props).toEqual({ isRoot: true });
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
test("an incident created with none gets the template's", async () => {
|
|
181
|
+
template = templateWith({ Impact: "High", Category: "Network" });
|
|
182
|
+
|
|
183
|
+
const created: Incident = await runBeforeCreate(newIncident());
|
|
184
|
+
|
|
185
|
+
expect(created.customFields).toEqual({
|
|
186
|
+
Impact: "High",
|
|
187
|
+
Category: "Network",
|
|
188
|
+
});
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
test("merge into the incident's own values: the template fills only the gaps", async () => {
|
|
192
|
+
template = templateWith({ Impact: "High", Category: "Network" });
|
|
193
|
+
|
|
194
|
+
const created: Incident = await runBeforeCreate(
|
|
195
|
+
newIncident({ Impact: "Low", Ticket: "OPS-7" }),
|
|
196
|
+
);
|
|
197
|
+
|
|
198
|
+
expect(created.customFields).toEqual({
|
|
199
|
+
Impact: "Low",
|
|
200
|
+
Category: "Network",
|
|
201
|
+
Ticket: "OPS-7",
|
|
202
|
+
});
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
test("0, false and null from the caller are kept, not filled over", async () => {
|
|
206
|
+
template = templateWith({
|
|
207
|
+
"Estimated Duration": 5,
|
|
208
|
+
Acknowledgement: true,
|
|
209
|
+
Impact: "High",
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
const created: Incident = await runBeforeCreate(
|
|
213
|
+
newIncident({
|
|
214
|
+
"Estimated Duration": 0,
|
|
215
|
+
Acknowledgement: false,
|
|
216
|
+
Impact: null,
|
|
217
|
+
}),
|
|
218
|
+
);
|
|
219
|
+
|
|
220
|
+
expect(created.customFields).toEqual({
|
|
221
|
+
"Estimated Duration": 0,
|
|
222
|
+
Acknowledgement: false,
|
|
223
|
+
Impact: null,
|
|
224
|
+
});
|
|
225
|
+
});
|
|
226
|
+
|
|
227
|
+
test("a template value that no longer fits its field does not refuse the incident", async () => {
|
|
228
|
+
// "Critical" was removed from Impact after the template was saved.
|
|
229
|
+
template = templateWith({ Impact: "Critical" });
|
|
230
|
+
|
|
231
|
+
const created: Incident = await runBeforeCreate(
|
|
232
|
+
newIncident({ Acknowledgement: true }),
|
|
233
|
+
);
|
|
234
|
+
|
|
235
|
+
expect(created.customFields).toEqual({
|
|
236
|
+
Impact: "Critical",
|
|
237
|
+
Acknowledgement: true,
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
// Only the caller's own values were checked.
|
|
241
|
+
expect(definitionFindBy).toHaveBeenCalledTimes(1);
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
test("the caller's values are still checked", async () => {
|
|
245
|
+
template = templateWith({ Impact: "High" });
|
|
246
|
+
|
|
247
|
+
await expect(
|
|
248
|
+
runBeforeCreate(newIncident({ Impact: "Critical" })),
|
|
249
|
+
).rejects.toThrow('"Critical" is not one of the options for "Impact"');
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
test("a template without values leaves the incident's as they are", async () => {
|
|
253
|
+
for (const templateCustomFields of [undefined, null, {}]) {
|
|
254
|
+
template = templateWith(templateCustomFields);
|
|
255
|
+
|
|
256
|
+
const withValues: Incident = await runBeforeCreate(
|
|
257
|
+
newIncident({ Ticket: "OPS-7" }),
|
|
258
|
+
);
|
|
259
|
+
expect(withValues.customFields).toEqual({ Ticket: "OPS-7" });
|
|
260
|
+
|
|
261
|
+
const withoutValues: Incident = await runBeforeCreate(newIncident());
|
|
262
|
+
expect(withoutValues.customFields).toBeUndefined();
|
|
263
|
+
}
|
|
264
|
+
});
|
|
265
|
+
|
|
266
|
+
test("no template found, nothing copied", async () => {
|
|
267
|
+
template = null;
|
|
268
|
+
|
|
269
|
+
const created: Incident = await runBeforeCreate(newIncident());
|
|
270
|
+
|
|
271
|
+
expect(created.customFields).toBeUndefined();
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
test("the mapping from monitors runs after the copy, and wins for a mapped field", async () => {
|
|
275
|
+
template = templateWith({ Impact: "High", Category: "Network" });
|
|
276
|
+
|
|
277
|
+
let seenByMapping: JSONObject | undefined = undefined;
|
|
278
|
+
|
|
279
|
+
applyMappingsToCreate.mockImplementation(((data: {
|
|
280
|
+
createBy: CreateBy<Incident>;
|
|
281
|
+
}) => {
|
|
282
|
+
seenByMapping = { ...(data.createBy.data.customFields || {}) };
|
|
283
|
+
data.createBy.data.customFields = {
|
|
284
|
+
...(data.createBy.data.customFields || {}),
|
|
285
|
+
Impact: "Copied From Monitor",
|
|
286
|
+
};
|
|
287
|
+
return Promise.resolve();
|
|
288
|
+
}) as never);
|
|
289
|
+
|
|
290
|
+
const created: Incident = await runBeforeCreate(newIncident());
|
|
291
|
+
|
|
292
|
+
expect(seenByMapping).toEqual({ Impact: "High", Category: "Network" });
|
|
293
|
+
expect(created.customFields).toEqual({
|
|
294
|
+
Impact: "Copied From Monitor",
|
|
295
|
+
Category: "Network",
|
|
296
|
+
});
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
test("a root create from a template copies them too", async () => {
|
|
300
|
+
template = templateWith({ Impact: "High" });
|
|
301
|
+
|
|
302
|
+
const incident: Incident = newIncident();
|
|
303
|
+
incident.projectId = projectId;
|
|
304
|
+
|
|
305
|
+
const created: Incident = await runBeforeCreate(incident, {
|
|
306
|
+
isRoot: true,
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
expect(created.customFields).toEqual({ Impact: "High" });
|
|
310
|
+
});
|
|
311
|
+
});
|
|
@@ -0,0 +1,363 @@
|
|
|
1
|
+
import IncidentTemplate from "../../../Models/DatabaseModels/IncidentTemplate";
|
|
2
|
+
import StatusPage from "../../../Models/DatabaseModels/StatusPage";
|
|
3
|
+
import IncidentTemplateService from "../../../Server/Services/IncidentTemplateService";
|
|
4
|
+
import StatusPageService from "../../../Server/Services/StatusPageService";
|
|
5
|
+
import CreateBy from "../../../Server/Types/Database/CreateBy";
|
|
6
|
+
import { OnCreate, OnUpdate } from "../../../Server/Types/Database/Hooks";
|
|
7
|
+
import UpdateBy from "../../../Server/Types/Database/UpdateBy";
|
|
8
|
+
import ProjectScopedReferenceValidator from "../../../Server/Utils/Database/ProjectScopedReferenceValidator";
|
|
9
|
+
import StatusPageReadAccess from "../../../Server/Utils/StatusPage/StatusPageReadAccess";
|
|
10
|
+
import DatabaseCommonInteractionProps from "../../../Types/BaseDatabase/DatabaseCommonInteractionProps";
|
|
11
|
+
import Dictionary from "../../../Types/Dictionary";
|
|
12
|
+
import NotAuthorizedException from "../../../Types/Exception/NotAuthorizedException";
|
|
13
|
+
import ObjectID from "../../../Types/ObjectID";
|
|
14
|
+
import Permission from "../../../Types/Permission";
|
|
15
|
+
import getJestMockFunction, { MockFunction } from "../../MockType";
|
|
16
|
+
import {
|
|
17
|
+
afterEach,
|
|
18
|
+
beforeEach,
|
|
19
|
+
describe,
|
|
20
|
+
expect,
|
|
21
|
+
jest,
|
|
22
|
+
test,
|
|
23
|
+
} from "@jest/globals";
|
|
24
|
+
|
|
25
|
+
/*
|
|
26
|
+
* An incident template can limit the incidents declared from it to status
|
|
27
|
+
* pages (IncidentTemplate.statusPages). IncidentTemplateService owns two
|
|
28
|
+
* things about that list:
|
|
29
|
+
*
|
|
30
|
+
* - isScopedToStatusPages follows writes to it and nothing else. It is how
|
|
31
|
+
* a template whose pages were all deleted (the join rows cascade away)
|
|
32
|
+
* still declares incidents limited - to nothing - instead of incidents
|
|
33
|
+
* that reach every status page listing their monitors;
|
|
34
|
+
* - the pages a non-root caller adds must be pages they can read. Incident
|
|
35
|
+
* members may edit templates, and a template's pages are copied onto
|
|
36
|
+
* every incident declared from it, so this is the same rule as picking an
|
|
37
|
+
* incident's pages.
|
|
38
|
+
*
|
|
39
|
+
* The database is stubbed: stored templates by a stub of findBy, and which
|
|
40
|
+
* status pages the caller can read by a stub of the status page service.
|
|
41
|
+
*/
|
|
42
|
+
|
|
43
|
+
const projectId: ObjectID = new ObjectID(
|
|
44
|
+
"5d7f3c0a-4c55-4d3e-9a3e-2d4a7d1c9e01",
|
|
45
|
+
);
|
|
46
|
+
const templateId: string = "a1b2c3d4-0000-4000-8000-0000000000aa";
|
|
47
|
+
|
|
48
|
+
const PAGE_A: string = "b0000000-0000-4000-8000-00000000000a";
|
|
49
|
+
const PAGE_B: string = "b0000000-0000-4000-8000-00000000000b";
|
|
50
|
+
const HIDDEN_PAGE_X: string = "b0000000-0000-4000-8000-0000000000f1";
|
|
51
|
+
|
|
52
|
+
const MEMBER_PROPS: DatabaseCommonInteractionProps = {
|
|
53
|
+
userId: new ObjectID("5d7f3c0a-4c55-4d3e-9a3e-2d4a7d1c9e02"),
|
|
54
|
+
tenantId: projectId,
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
type OnBeforeCreate = (
|
|
58
|
+
createBy: CreateBy<IncidentTemplate>,
|
|
59
|
+
) => Promise<OnCreate<IncidentTemplate>>;
|
|
60
|
+
type OnBeforeUpdate = (
|
|
61
|
+
updateBy: UpdateBy<IncidentTemplate>,
|
|
62
|
+
) => Promise<OnUpdate<IncidentTemplate>>;
|
|
63
|
+
|
|
64
|
+
function statusPage(id: string): StatusPage {
|
|
65
|
+
const page: StatusPage = new StatusPage();
|
|
66
|
+
page._id = id;
|
|
67
|
+
return page;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
let storedTemplates: Array<IncidentTemplate> = [];
|
|
71
|
+
let readable: Array<string> | null = [];
|
|
72
|
+
let templateFindBy: MockFunction;
|
|
73
|
+
let statusPageFindBy: MockFunction;
|
|
74
|
+
|
|
75
|
+
function storedTemplate(statusPageIds: Array<string>): IncidentTemplate {
|
|
76
|
+
const template: IncidentTemplate = new IncidentTemplate();
|
|
77
|
+
template._id = templateId;
|
|
78
|
+
template.projectId = projectId;
|
|
79
|
+
template.statusPages = statusPageIds.map(statusPage);
|
|
80
|
+
return template;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
async function runBeforeCreate(
|
|
84
|
+
data: IncidentTemplate,
|
|
85
|
+
props: DatabaseCommonInteractionProps = MEMBER_PROPS,
|
|
86
|
+
): Promise<IncidentTemplate> {
|
|
87
|
+
const onCreate: OnCreate<IncidentTemplate> = await (
|
|
88
|
+
IncidentTemplateService as unknown as { onBeforeCreate: OnBeforeCreate }
|
|
89
|
+
).onBeforeCreate({ data, props });
|
|
90
|
+
|
|
91
|
+
return onCreate.createBy.data;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
async function runBeforeUpdate(
|
|
95
|
+
data: Record<string, unknown>,
|
|
96
|
+
props: DatabaseCommonInteractionProps = MEMBER_PROPS,
|
|
97
|
+
): Promise<Record<string, unknown>> {
|
|
98
|
+
const onUpdate: OnUpdate<IncidentTemplate> = await (
|
|
99
|
+
IncidentTemplateService as unknown as { onBeforeUpdate: OnBeforeUpdate }
|
|
100
|
+
).onBeforeUpdate({
|
|
101
|
+
query: { _id: templateId },
|
|
102
|
+
data: data as UpdateBy<IncidentTemplate>["data"],
|
|
103
|
+
props: props,
|
|
104
|
+
limit: 1,
|
|
105
|
+
skip: 0,
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
return onUpdate.updateBy.data as unknown as Record<string, unknown>;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
beforeEach(() => {
|
|
112
|
+
storedTemplates = [storedTemplate([])];
|
|
113
|
+
readable = [PAGE_A, PAGE_B];
|
|
114
|
+
|
|
115
|
+
templateFindBy = getJestMockFunction();
|
|
116
|
+
templateFindBy.mockImplementation(() => {
|
|
117
|
+
return Promise.resolve(storedTemplates);
|
|
118
|
+
});
|
|
119
|
+
jest
|
|
120
|
+
.spyOn(IncidentTemplateService, "findBy")
|
|
121
|
+
.mockImplementation(templateFindBy as never);
|
|
122
|
+
|
|
123
|
+
statusPageFindBy = getJestMockFunction();
|
|
124
|
+
statusPageFindBy.mockImplementation(
|
|
125
|
+
(findBy: { query: { _id: unknown } }): Promise<Array<StatusPage>> => {
|
|
126
|
+
if (readable === null) {
|
|
127
|
+
return Promise.reject(
|
|
128
|
+
new NotAuthorizedException(
|
|
129
|
+
"You do not have permissions to read Status Page.",
|
|
130
|
+
),
|
|
131
|
+
);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const operator: { objectLiteralParameters?: Dictionary<unknown> } = findBy
|
|
135
|
+
.query._id as { objectLiteralParameters?: Dictionary<unknown> };
|
|
136
|
+
|
|
137
|
+
return Promise.resolve(
|
|
138
|
+
(
|
|
139
|
+
Object.values(operator.objectLiteralParameters || {}) as Array<
|
|
140
|
+
Array<string>
|
|
141
|
+
>
|
|
142
|
+
)
|
|
143
|
+
.flat()
|
|
144
|
+
.map((id: string): string => {
|
|
145
|
+
return id.toLowerCase();
|
|
146
|
+
})
|
|
147
|
+
.filter((id: string): boolean => {
|
|
148
|
+
return readable!.includes(id);
|
|
149
|
+
})
|
|
150
|
+
.map(statusPage),
|
|
151
|
+
);
|
|
152
|
+
},
|
|
153
|
+
);
|
|
154
|
+
jest
|
|
155
|
+
.spyOn(StatusPageService, "findBy")
|
|
156
|
+
.mockImplementation(statusPageFindBy as never);
|
|
157
|
+
|
|
158
|
+
jest
|
|
159
|
+
.spyOn(ProjectScopedReferenceValidator, "validateReferencesBelongToProject")
|
|
160
|
+
.mockResolvedValue(undefined as never);
|
|
161
|
+
jest
|
|
162
|
+
.spyOn(ProjectScopedReferenceValidator, "getHeldRelationIds")
|
|
163
|
+
.mockResolvedValue(new Map() as never);
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
afterEach(() => {
|
|
167
|
+
jest.restoreAllMocks();
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
describe("IncidentTemplateService: isScopedToStatusPages follows the template's status pages", () => {
|
|
171
|
+
test("a template created with pages is scoped", async () => {
|
|
172
|
+
const created: IncidentTemplate = await runBeforeCreate(
|
|
173
|
+
Object.assign(new IncidentTemplate(), {
|
|
174
|
+
statusPages: [statusPage(PAGE_A)],
|
|
175
|
+
}),
|
|
176
|
+
);
|
|
177
|
+
|
|
178
|
+
expect(created.isScopedToStatusPages).toBe(true);
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
test("a template created without pages is not, whatever the client sent", async () => {
|
|
182
|
+
const created: IncidentTemplate = await runBeforeCreate(
|
|
183
|
+
Object.assign(new IncidentTemplate(), {
|
|
184
|
+
isScopedToStatusPages: true,
|
|
185
|
+
}),
|
|
186
|
+
);
|
|
187
|
+
|
|
188
|
+
expect(created.isScopedToStatusPages).toBe(false);
|
|
189
|
+
|
|
190
|
+
const empty: IncidentTemplate = await runBeforeCreate(
|
|
191
|
+
Object.assign(new IncidentTemplate(), {
|
|
192
|
+
statusPages: [],
|
|
193
|
+
isScopedToStatusPages: true,
|
|
194
|
+
}),
|
|
195
|
+
);
|
|
196
|
+
|
|
197
|
+
expect(empty.isScopedToStatusPages).toBe(false);
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
test("writing pages scopes it, and clearing them unscopes it", async () => {
|
|
201
|
+
expect(
|
|
202
|
+
(await runBeforeUpdate({ statusPages: [PAGE_A] }))[
|
|
203
|
+
"isScopedToStatusPages"
|
|
204
|
+
],
|
|
205
|
+
).toBe(true);
|
|
206
|
+
|
|
207
|
+
storedTemplates = [storedTemplate([PAGE_A])];
|
|
208
|
+
|
|
209
|
+
expect(
|
|
210
|
+
(await runBeforeUpdate({ statusPages: [] }))["isScopedToStatusPages"],
|
|
211
|
+
).toBe(false);
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
test("a client's flag is dropped; an update that does not write the list leaves the flag alone", async () => {
|
|
215
|
+
const data: Record<string, unknown> = await runBeforeUpdate({
|
|
216
|
+
name: "Region East outage",
|
|
217
|
+
isScopedToStatusPages: false,
|
|
218
|
+
});
|
|
219
|
+
|
|
220
|
+
expect(data).not.toHaveProperty("isScopedToStatusPages");
|
|
221
|
+
});
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
describe("IncidentTemplateService: the status pages a caller adds must be pages they can read", () => {
|
|
225
|
+
test("creating a template with a page the caller cannot read is refused", async () => {
|
|
226
|
+
readable = [PAGE_A];
|
|
227
|
+
|
|
228
|
+
await expect(
|
|
229
|
+
runBeforeCreate(
|
|
230
|
+
Object.assign(new IncidentTemplate(), {
|
|
231
|
+
statusPages: [statusPage(PAGE_A), statusPage(PAGE_B)],
|
|
232
|
+
}),
|
|
233
|
+
),
|
|
234
|
+
).rejects.toThrow(
|
|
235
|
+
StatusPageReadAccess.getRefusalMessage("incident template"),
|
|
236
|
+
);
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
test("a caller without status page access cannot give a template pages", async () => {
|
|
240
|
+
readable = null;
|
|
241
|
+
|
|
242
|
+
await expect(
|
|
243
|
+
runBeforeCreate(
|
|
244
|
+
Object.assign(new IncidentTemplate(), {
|
|
245
|
+
statusPages: [statusPage(PAGE_A)],
|
|
246
|
+
}),
|
|
247
|
+
{
|
|
248
|
+
...MEMBER_PROPS,
|
|
249
|
+
userTenantAccessPermission: {
|
|
250
|
+
[projectId.toString()]: {
|
|
251
|
+
projectId: projectId,
|
|
252
|
+
_type: "UserTenantAccessPermission",
|
|
253
|
+
permissions: [
|
|
254
|
+
{
|
|
255
|
+
_type: "UserPermission",
|
|
256
|
+
permission: Permission.IncidentMember,
|
|
257
|
+
labelIds: [],
|
|
258
|
+
isBlockPermission: false,
|
|
259
|
+
},
|
|
260
|
+
],
|
|
261
|
+
},
|
|
262
|
+
},
|
|
263
|
+
},
|
|
264
|
+
),
|
|
265
|
+
).rejects.toBeInstanceOf(NotAuthorizedException);
|
|
266
|
+
});
|
|
267
|
+
|
|
268
|
+
test("adding a page the caller cannot read to a template is refused", async () => {
|
|
269
|
+
readable = [PAGE_A];
|
|
270
|
+
|
|
271
|
+
await expect(
|
|
272
|
+
runBeforeUpdate({ statusPages: [PAGE_A, PAGE_B] }),
|
|
273
|
+
).rejects.toBeInstanceOf(NotAuthorizedException);
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
test("a page the template already holds is not added, so it is not checked", async () => {
|
|
277
|
+
readable = [PAGE_A];
|
|
278
|
+
storedTemplates = [storedTemplate([PAGE_A, HIDDEN_PAGE_X])];
|
|
279
|
+
|
|
280
|
+
const data: Record<string, unknown> = await runBeforeUpdate({
|
|
281
|
+
statusPages: [PAGE_A, HIDDEN_PAGE_X],
|
|
282
|
+
});
|
|
283
|
+
|
|
284
|
+
expect(data["isScopedToStatusPages"]).toBe(true);
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
test("reads the templates as root, limited to the caller's project", async () => {
|
|
288
|
+
await runBeforeUpdate({ statusPages: [PAGE_A] });
|
|
289
|
+
|
|
290
|
+
const findBy: {
|
|
291
|
+
query: Record<string, unknown>;
|
|
292
|
+
props: DatabaseCommonInteractionProps;
|
|
293
|
+
} = templateFindBy.mock.calls[0]![0];
|
|
294
|
+
|
|
295
|
+
expect(findBy.props).toEqual({ isRoot: true });
|
|
296
|
+
expect(findBy.query["projectId"]).toBe(projectId);
|
|
297
|
+
expect(findBy.query["_id"]).toBe(templateId);
|
|
298
|
+
});
|
|
299
|
+
|
|
300
|
+
test("a root caller adds any page", async () => {
|
|
301
|
+
readable = null;
|
|
302
|
+
|
|
303
|
+
const data: Record<string, unknown> = await runBeforeUpdate(
|
|
304
|
+
{ statusPages: [PAGE_B] },
|
|
305
|
+
{ isRoot: true },
|
|
306
|
+
);
|
|
307
|
+
|
|
308
|
+
expect(data["isScopedToStatusPages"]).toBe(true);
|
|
309
|
+
expect(statusPageFindBy).not.toHaveBeenCalled();
|
|
310
|
+
// Only the project lookup a root update without a tenant always makes.
|
|
311
|
+
for (const call of templateFindBy.mock.calls) {
|
|
312
|
+
expect(
|
|
313
|
+
(call[0] as { select: Record<string, unknown> }).select,
|
|
314
|
+
).not.toHaveProperty("statusPages");
|
|
315
|
+
}
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
test("clearing the list checks nothing", async () => {
|
|
319
|
+
readable = null;
|
|
320
|
+
storedTemplates = [storedTemplate([PAGE_A])];
|
|
321
|
+
|
|
322
|
+
await runBeforeUpdate({ statusPages: [] });
|
|
323
|
+
|
|
324
|
+
expect(statusPageFindBy).not.toHaveBeenCalled();
|
|
325
|
+
});
|
|
326
|
+
});
|
|
327
|
+
|
|
328
|
+
describe("IncidentTemplate.isScopedToStatusPages column", () => {
|
|
329
|
+
function access(column: string): {
|
|
330
|
+
create: Array<Permission>;
|
|
331
|
+
read: Array<Permission>;
|
|
332
|
+
update: Array<Permission>;
|
|
333
|
+
} {
|
|
334
|
+
const columnAccess: {
|
|
335
|
+
create?: Array<Permission>;
|
|
336
|
+
read?: Array<Permission>;
|
|
337
|
+
update?: Array<Permission>;
|
|
338
|
+
} = new IncidentTemplate().getColumnAccessControlFor(column) || {};
|
|
339
|
+
|
|
340
|
+
return {
|
|
341
|
+
create: (columnAccess.create || []).slice(),
|
|
342
|
+
read: (columnAccess.read || []).slice(),
|
|
343
|
+
update: (columnAccess.update || []).slice(),
|
|
344
|
+
};
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
test("has the access control of the template's status pages", () => {
|
|
348
|
+
expect(access("isScopedToStatusPages")).toEqual(access("statusPages"));
|
|
349
|
+
});
|
|
350
|
+
|
|
351
|
+
test("is computed, required, false by default and hidden from the API docs", () => {
|
|
352
|
+
const template: IncidentTemplate = new IncidentTemplate();
|
|
353
|
+
|
|
354
|
+
expect(template.getTableColumnMetadata("isScopedToStatusPages")).toEqual(
|
|
355
|
+
expect.objectContaining({
|
|
356
|
+
computed: true,
|
|
357
|
+
required: true,
|
|
358
|
+
hideColumnInDocumentation: true,
|
|
359
|
+
defaultValue: false,
|
|
360
|
+
}),
|
|
361
|
+
);
|
|
362
|
+
});
|
|
363
|
+
});
|