@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.
Files changed (440) hide show
  1. package/Models/DatabaseModels/Incident.ts +267 -1
  2. package/Models/DatabaseModels/IncidentCustomField.ts +202 -0
  3. package/Models/DatabaseModels/IncidentEpisode.ts +30 -0
  4. package/Models/DatabaseModels/IncidentTemplate.ts +126 -1
  5. package/Models/DatabaseModels/StatusPage.ts +55 -0
  6. package/Models/DatabaseModels/StatusPageSubscriber.ts +128 -0
  7. package/Server/API/IncidentAPI.ts +162 -0
  8. package/Server/API/StatusPageAPI.ts +487 -171
  9. package/Server/API/StatusPageSubscriberAPI.ts +63 -15
  10. package/Server/Infrastructure/Postgres/SchemaMigrations/1795300000000-SkipHiddenIncidentCreatedNotifications.ts +49 -0
  11. package/Server/Infrastructure/Postgres/SchemaMigrations/1795400000000-AddIncidentStatusPageScope.ts +108 -0
  12. package/Server/Infrastructure/Postgres/SchemaMigrations/1795500000000-AddIncidentTemplateStatusPageScopeFlag.ts +33 -0
  13. package/Server/Infrastructure/Postgres/SchemaMigrations/1795600000000-AddStatusPageSubscriberUnsubscribeToken.ts +51 -0
  14. package/Server/Infrastructure/Postgres/SchemaMigrations/1795700000000-AddStatusPageSubscriberIsAddedByTeam.ts +33 -0
  15. package/Server/Infrastructure/Postgres/SchemaMigrations/1795800000000-AddIncidentCustomFieldCreateAndNotificationSettings.ts +168 -0
  16. package/Server/Infrastructure/Postgres/SchemaMigrations/1795900000000-AddSubscriberNotificationClaimedAt.ts +44 -0
  17. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +14 -0
  18. package/Server/Infrastructure/Semaphore.ts +10 -0
  19. package/Server/Middleware/IdentityRateLimit.ts +108 -3
  20. package/Server/Middleware/SubscriberNotificationPreviewRateLimit.ts +237 -0
  21. package/Server/Middleware/SubscriberNotificationTestSendRateLimit.ts +304 -0
  22. package/Server/Services/DatabaseService.ts +93 -10
  23. package/Server/Services/IncidentCustomFieldService.ts +276 -1
  24. package/Server/Services/IncidentEpisodePublicNoteService.ts +28 -0
  25. package/Server/Services/IncidentEpisodeService.ts +15 -0
  26. package/Server/Services/IncidentEpisodeStateTimelineService.ts +27 -1
  27. package/Server/Services/IncidentPublicNoteService.ts +30 -1
  28. package/Server/Services/IncidentService.ts +1535 -65
  29. package/Server/Services/IncidentStateTimelineService.ts +13 -0
  30. package/Server/Services/IncidentTemplateService.ts +109 -0
  31. package/Server/Services/ScheduledMaintenancePublicNoteService.ts +30 -1
  32. package/Server/Services/ScheduledMaintenanceService.ts +68 -18
  33. package/Server/Services/SmsService.ts +10 -0
  34. package/Server/Services/StatusPageService.ts +65 -8
  35. package/Server/Services/StatusPageSubscriberNotificationTemplateService.ts +299 -37
  36. package/Server/Services/StatusPageSubscriberNotificationTemplateStatusPageService.ts +129 -0
  37. package/Server/Services/StatusPageSubscriberService.ts +1161 -64
  38. package/Server/Types/Markdown.ts +153 -6
  39. package/Server/Types/Workflow/Components/Email.ts +61 -2
  40. package/Server/Utils/CustomField/CustomFieldRename.ts +378 -0
  41. package/Server/Utils/DataSource/EgressGuard.ts +66 -21
  42. package/Server/Utils/Mail/PinnedSmtpSocket.ts +130 -0
  43. package/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.ts +10 -0
  44. package/Server/Utils/SSRFProtection.ts +76 -16
  45. package/Server/Utils/StatusPage/IncidentStatusPageScope.ts +948 -0
  46. package/Server/Utils/StatusPage/IncidentSubscriberAudienceBuilder.ts +656 -0
  47. package/Server/Utils/StatusPage/IncidentTemplateVariableBuilder.ts +805 -0
  48. package/Server/Utils/StatusPage/StatusPageExclusion.ts +18 -0
  49. package/Server/Utils/StatusPage/StatusPageReadAccess.ts +125 -0
  50. package/Server/Utils/StatusPage/StatusPageSubscriberUnsubscribeNotice.ts +151 -0
  51. package/Server/Utils/StatusPage/StatusPageSubscriberUnsubscribeToken.ts +70 -0
  52. package/Server/Utils/StatusPage/SubscriberIncidentEmailBuilder.ts +421 -0
  53. package/Server/Utils/StatusPage/SubscriberNotificationClaim.ts +107 -0
  54. package/Server/Utils/StatusPage/SubscriberNotificationDeliveryRecord.ts +1049 -0
  55. package/Server/Utils/StatusPage/SubscriberNotificationFanOut.ts +180 -0
  56. package/Server/Utils/StatusPage/SubscriberNotificationPreviewBuilder.ts +839 -0
  57. package/Server/Utils/StatusPage/SubscriberNotificationResendAccess.ts +393 -0
  58. package/Server/Utils/StatusPage/SubscriberNotificationRunLimit.ts +246 -0
  59. package/Server/Utils/StatusPage/SubscriberNotificationTiming.ts +133 -0
  60. package/Server/Utils/StatusPage/SubscriberTemplateIncidentRecordAccess.ts +215 -0
  61. package/Server/Utils/StatusPageResource.ts +51 -20
  62. package/Server/Utils/VM/VMAPI.ts +1 -0
  63. package/Server/Utils/VM/VMRunner.ts +10 -0
  64. package/Server/Utils/Workflow/OAuth2TokenClient.ts +10 -0
  65. package/Server/Views/Partials/SensitiveUrlToken.ejs +8 -5
  66. package/Tests/App/Accounts/RegisterVerifyEmail.test.tsx +748 -0
  67. package/Tests/App/Accounts/ResendVerificationEmail.test.tsx +1222 -0
  68. package/Tests/App/Accounts/VerificationEmailResendUtils.test.ts +797 -0
  69. package/Tests/App/Accounts/VerifyEmailPending.test.tsx +538 -0
  70. package/Tests/App/Accounts/VerifyEmailResend.test.tsx +779 -0
  71. package/Tests/App/Dashboard/CustomFieldsSettingsIncidentOptions.test.tsx +357 -0
  72. package/Tests/App/Dashboard/EventNotes.test.tsx +776 -0
  73. package/Tests/App/Dashboard/EventNotesPages.test.tsx +119 -0
  74. package/Tests/App/Dashboard/EventNotesUtil.test.ts +116 -17
  75. package/Tests/App/Dashboard/EventOverviewPages.test.tsx +242 -5
  76. package/Tests/App/Dashboard/IncidentChangeStateNotifyDefault.test.tsx +91 -1
  77. package/Tests/App/Dashboard/IncidentCreateDetailsStep.test.tsx +643 -0
  78. package/Tests/App/Dashboard/IncidentCreateFromAlerts.test.tsx +8 -1
  79. package/Tests/App/Dashboard/IncidentCreateStatusPageScope.test.tsx +601 -0
  80. package/Tests/App/Dashboard/IncidentCustomFieldTemplateVariables.test.tsx +386 -0
  81. package/Tests/App/Dashboard/IncidentNoteTemplatePlaceholders.test.tsx +124 -0
  82. package/Tests/App/Dashboard/IncidentNoteTemplateVariablesLoader.test.ts +305 -0
  83. package/Tests/App/Dashboard/IncidentOverviewNotifyDefault.test.tsx +112 -0
  84. package/Tests/App/Dashboard/IncidentSettingsRenotifyOnPublish.test.tsx +674 -0
  85. package/Tests/App/Dashboard/IncidentSettingsStatusPageScope.test.tsx +1051 -0
  86. package/Tests/App/Dashboard/IncidentTemplateCustomFields.test.tsx +384 -0
  87. package/Tests/App/Dashboard/IncidentTemplateStatusPageScopeCard.test.tsx +215 -0
  88. package/Tests/App/Dashboard/PublicNotePagesNotifyDefault.test.tsx +113 -1
  89. package/Tests/App/Dashboard/SubscriberAudienceSummary.test.tsx +512 -0
  90. package/Tests/App/Dashboard/SubscriberNotificationPreviewModal.test.tsx +837 -0
  91. package/Tests/App/Dashboard/SubscriberNotificationStatusLabel.test.tsx +88 -0
  92. package/Tests/App/Dashboard/SubscriberNotificationStatusResend.test.tsx +473 -0
  93. package/Tests/App/Dashboard/SubscriberTemplateLivePreview.test.tsx +196 -0
  94. package/Tests/App/Dashboard/TeamAddedSubscribersUnsubscribedNotice.test.tsx +248 -0
  95. package/Tests/App/SensitiveUrlTokenBootstrap.test.ts +64 -3
  96. package/Tests/App/StatusPage/StatusPageUnsubscribePage.test.tsx +412 -0
  97. package/Tests/Models/IncidentCustomFieldApiSchemaContract.test.ts +217 -0
  98. package/Tests/Models/IncidentCustomFieldCreateSettingsColumns.test.ts +252 -0
  99. package/Tests/Models/StatusPageSubscriberUnsubscribeColumns.test.ts +218 -0
  100. package/Tests/Server/API/ExpiredSessionRouteGuards.test.ts +7 -0
  101. package/Tests/Server/API/IncidentSubscriberAudienceAPI.test.ts +1408 -0
  102. package/Tests/Server/API/StatusPageIncidentScope.test.ts +1868 -0
  103. package/Tests/Server/API/StatusPageIncidentScopePostgres.test.ts +790 -0
  104. package/Tests/Server/API/StatusPageManageSubscriptionRecipient.test.ts +10 -1
  105. package/Tests/Server/API/StatusPageManageSubscriptionTemplateVariables.test.ts +206 -18
  106. package/Tests/Server/API/StatusPagePostmortemVisibility.test.ts +14 -2
  107. package/Tests/Server/API/StatusPageSubscriberCreateResponse.test.ts +217 -0
  108. package/Tests/Server/API/StatusPageSubscriberOwnership.test.ts +103 -2
  109. package/Tests/Server/API/StatusPageUnsubscribeAPI.test.ts +396 -0
  110. package/Tests/Server/Infrastructure/Postgres/AddIncidentStatusPageScopeMigration.test.ts +395 -0
  111. package/Tests/Server/Infrastructure/Postgres/AddIncidentTemplateStatusPageScopeFlagMigration.test.ts +150 -0
  112. package/Tests/Server/Infrastructure/Postgres/AddSubscriberNotificationClaimedAtMigration.test.ts +156 -0
  113. package/Tests/Server/Infrastructure/Postgres/SkipHiddenIncidentCreatedNotificationsMigration.test.ts +410 -0
  114. package/Tests/Server/Middleware/IdentityRateLimit.test.ts +551 -1
  115. package/Tests/Server/Middleware/SubscriberNotificationPreviewRateLimit.test.ts +238 -0
  116. package/Tests/Server/Middleware/SubscriberNotificationTestSendRateLimit.test.ts +245 -0
  117. package/Tests/Server/Services/AddStatusPageSubscriberUnsubscribeTokenMigration.test.ts +152 -0
  118. package/Tests/Server/Services/CrossProjectRelationWriteGuard.test.ts +221 -36
  119. package/Tests/Server/Services/DatabaseServiceCompareAndSetColumns.test.ts +191 -0
  120. package/Tests/Server/Services/IncidentCreatedRenotifyOnPublish.test.ts +681 -0
  121. package/Tests/Server/Services/IncidentCreatedResend.test.ts +775 -0
  122. package/Tests/Server/Services/IncidentCustomFieldRenamePostgres.test.ts +713 -0
  123. package/Tests/Server/Services/IncidentCustomFieldService.test.ts +751 -0
  124. package/Tests/Server/Services/IncidentCustomFieldValueValidation.test.ts +556 -0
  125. package/Tests/Server/Services/IncidentStatusPageScope.test.ts +2971 -0
  126. package/Tests/Server/Services/IncidentStatusPageScopeFeed.test.ts +131 -0
  127. package/Tests/Server/Services/IncidentStatusPageScopePostgres.test.ts +625 -0
  128. package/Tests/Server/Services/IncidentTemplateCustomFieldsCopy.test.ts +311 -0
  129. package/Tests/Server/Services/IncidentTemplateStatusPageScope.test.ts +363 -0
  130. package/Tests/Server/Services/PublicNoteEditFeedEventType.test.ts +213 -0
  131. package/Tests/Server/Services/PublicNoteResendAccess.test.ts +994 -0
  132. package/Tests/Server/Services/ScheduledMaintenanceSubscriberTemplateFormats.test.ts +289 -9
  133. package/Tests/Server/Services/SmsServiceFailIfNotSent.test.ts +67 -0
  134. package/Tests/Server/Services/StatusPageReportIncidentCounts.test.ts +610 -0
  135. package/Tests/Server/Services/StatusPageSubscriberAudienceCounts.test.ts +201 -0
  136. package/Tests/Server/Services/StatusPageSubscriberAudienceCountsPostgres.test.ts +271 -0
  137. package/Tests/Server/Services/StatusPageSubscriberConfirmationTemplateEscaping.test.ts +200 -0
  138. package/Tests/Server/Services/StatusPageSubscriberNotificationLogRedaction.test.ts +54 -0
  139. package/Tests/Server/Services/StatusPageSubscriberNotificationTemplateCompile.test.ts +37 -0
  140. package/Tests/Server/Services/StatusPageSubscriberNotificationTemplateIncidentRecordAccess.test.ts +772 -0
  141. package/Tests/Server/Services/StatusPageSubscriberNotificationTemplateLookup.test.ts +506 -0
  142. package/Tests/Server/Services/StatusPageSubscriberNotificationTemplateLookupPostgres.test.ts +261 -0
  143. package/Tests/Server/Services/StatusPageSubscriberReport.test.ts +21 -5
  144. package/Tests/Server/Services/StatusPageSubscriberUnsubscribe.test.ts +1618 -0
  145. package/Tests/Server/Services/StatusPageSubscriberUnsubscribeLinkSenders.test.ts +373 -0
  146. package/Tests/Server/Services/StatusPageSubscriberUnsubscribePostgres.test.ts +388 -0
  147. package/Tests/Server/Services/SubscriberNotificationInFlightRequeue.test.ts +500 -0
  148. package/Tests/Server/Types/MarkdownEmailLinks.test.ts +320 -0
  149. package/Tests/Server/Types/Workflow/Components/Email.test.ts +491 -1
  150. package/Tests/Server/Types/Workflow/Components/EmailSmtpPinning.test.ts +398 -0
  151. package/Tests/Server/Utils/CustomField/CustomFieldRename.test.ts +586 -0
  152. package/Tests/Server/Utils/DataSource/EgressGuard.test.ts +246 -10
  153. package/Tests/Server/Utils/DataSource/EgressGuardDeploymentConfig.test.ts +226 -0
  154. package/Tests/Server/Utils/DataSource/EgressGuardPinning.test.ts +131 -0
  155. package/Tests/Server/Utils/DataSource/HttpFetch.test.ts +4 -0
  156. package/Tests/Server/Utils/EgressPolicyEnvironment.ts +45 -0
  157. package/Tests/Server/Utils/Mail/PinnedSmtpSocket.test.ts +409 -0
  158. package/Tests/Server/Utils/Monitor/MonitorCriteriaObservationBuilderUnits.test.ts +23 -0
  159. package/Tests/Server/Utils/SSRFProtection.test.ts +4 -0
  160. package/Tests/Server/Utils/SSRFProtectionCloudServiceAddresses.test.ts +4 -0
  161. package/Tests/Server/Utils/SSRFProtectionPrivateNetwork.test.ts +4 -0
  162. package/Tests/Server/Utils/SSRFProtectionResolutionDetail.test.ts +314 -0
  163. package/Tests/Server/Utils/StatusPage/IncidentStatusPageScope.test.ts +1699 -0
  164. package/Tests/Server/Utils/StatusPage/IncidentStatusPageScopeQueriesPostgres.test.ts +508 -0
  165. package/Tests/Server/Utils/StatusPage/IncidentSubscriberAudienceCallerPermission.test.ts +246 -0
  166. package/Tests/Server/Utils/StatusPage/IncidentTemplateVariableBuilder.test.ts +1348 -0
  167. package/Tests/Server/Utils/StatusPage/StatusPageReadAccess.test.ts +221 -0
  168. package/Tests/Server/Utils/StatusPage/StatusPageSubscriberUnsubscribeNotice.test.ts +132 -0
  169. package/Tests/Server/Utils/StatusPage/StatusPageSubscriberUnsubscribeToken.test.ts +155 -0
  170. package/Tests/Server/Utils/StatusPage/SubscriberIncidentEmailBuilder.test.ts +708 -0
  171. package/Tests/Server/Utils/StatusPage/SubscriberNotificationClaim.test.ts +255 -0
  172. package/Tests/Server/Utils/StatusPage/SubscriberNotificationClaimPostgres.test.ts +528 -0
  173. package/Tests/Server/Utils/StatusPage/SubscriberNotificationDeliveryRecord.test.ts +1238 -0
  174. package/Tests/Server/Utils/StatusPage/SubscriberNotificationFanOut.test.ts +472 -0
  175. package/Tests/Server/Utils/StatusPage/SubscriberNotificationPreviewBuilder.test.ts +1168 -0
  176. package/Tests/Server/Utils/StatusPage/SubscriberNotificationRunLimit.test.ts +275 -0
  177. package/Tests/Server/Utils/StatusPage/SubscriberNotificationTiming.test.ts +131 -0
  178. package/Tests/Server/Utils/StatusPageResource.test.ts +98 -0
  179. package/Tests/Server/Utils/VM/VMRunnerPrivateNetworkWiring.test.ts +17 -0
  180. package/Tests/Server/Utils/VM/VMRunnerSsrf.test.ts +75 -0
  181. package/Tests/Types/CustomField/CustomFieldSavedViews.test.ts +247 -0
  182. package/Tests/Types/CustomField/CustomFieldTemplateValues.test.ts +186 -0
  183. package/Tests/Types/CustomField/CustomFieldTypeCorrespondence.test.ts +48 -0
  184. package/Tests/Types/CustomField/CustomFieldValueFormat.test.ts +215 -0
  185. package/Tests/Types/CustomField/CustomFieldValueValidator.test.ts +343 -0
  186. package/Tests/Types/CustomField/CustomFieldVariableKey.test.ts +364 -0
  187. package/Tests/Types/SafeHtml.test.ts +102 -0
  188. package/Tests/Types/StatusPage/IncidentCreatedRenotify.test.ts +419 -0
  189. package/Tests/Types/StatusPage/IncidentCreatedResend.test.ts +118 -0
  190. package/Tests/Types/StatusPage/IncidentScopeAddedPagesNotification.test.ts +558 -0
  191. package/Tests/Types/StatusPage/IncidentSubscriberAudience.test.ts +284 -0
  192. package/Tests/Types/StatusPage/StatusPageSubscriberUnsubscribe.test.ts +341 -0
  193. package/Tests/Types/StatusPage/SubscriberNotificationPreview.test.ts +196 -0
  194. package/Tests/Types/StatusPage/SubscriberNotificationResend.test.ts +201 -0
  195. package/Tests/Types/StatusPage/SubscriberNotificationTemplateCompiler.test.ts +277 -0
  196. package/Tests/Types/StatusPage/SubscriberNotificationTemplatePreview.test.ts +179 -0
  197. package/Tests/Types/StatusPage/SubscriberNotificationTemplateVariables.test.ts +324 -0
  198. package/Tests/Types/StatusPage/SubscriberUpdateNotification.test.ts +60 -13
  199. package/Tests/UI/Components/CustomFields/CustomFieldFormFields.test.ts +432 -0
  200. package/Tests/UI/Components/CustomFields/CustomFieldModelFormFields.test.tsx +685 -0
  201. package/Tests/UI/Components/CustomFields/CustomFieldsDetailOrder.test.tsx +469 -0
  202. package/Tests/UI/Components/Forms/ModelFormCustomFieldInputs.test.tsx +325 -0
  203. package/Tests/UI/Components/Forms/ModelFormDropdownOptionsRefused.test.tsx +358 -0
  204. package/Tests/UI/Components/ModelTable/CustomFieldColumns.test.tsx +22 -0
  205. package/Tests/UI/Monitor/NetworkPathView.test.tsx +289 -0
  206. package/Tests/Utils/Incident/IncidentNoteTemplateVariables.test.ts +623 -0
  207. package/Tests/Utils/Markdown/MarkdownEscape.test.ts +89 -0
  208. package/Tests/Utils/ProbeNetworkFailureUtil.test.ts +992 -0
  209. package/Tests/Utils/RequestFailedDetails.test.ts +575 -0
  210. package/Types/CustomField/CustomFieldOrder.ts +55 -0
  211. package/Types/CustomField/CustomFieldSavedViews.ts +225 -0
  212. package/Types/CustomField/CustomFieldTemplateMerge.ts +71 -0
  213. package/Types/CustomField/CustomFieldType.ts +14 -0
  214. package/Types/CustomField/CustomFieldValueFormat.ts +161 -0
  215. package/Types/CustomField/CustomFieldValueValidator.ts +488 -0
  216. package/Types/CustomField/CustomFieldVariableKey.ts +211 -0
  217. package/Types/SafeHtml.ts +93 -0
  218. package/Types/StatusPage/IncidentCreatedRenotify.ts +224 -0
  219. package/Types/StatusPage/IncidentCreatedResend.ts +108 -0
  220. package/Types/StatusPage/IncidentScopeAddedPagesNotification.ts +343 -0
  221. package/Types/StatusPage/IncidentSubscriberAudience.ts +332 -0
  222. package/Types/StatusPage/StatusPageSubscriberUnsubscribe.ts +405 -0
  223. package/Types/StatusPage/SubscriberNotificationInterruption.ts +32 -0
  224. package/Types/StatusPage/SubscriberNotificationPreview.ts +322 -0
  225. package/Types/StatusPage/SubscriberNotificationResend.ts +132 -0
  226. package/Types/StatusPage/SubscriberNotificationTemplateCompiler.ts +180 -0
  227. package/Types/StatusPage/SubscriberNotificationTemplatePreview.ts +301 -0
  228. package/Types/StatusPage/SubscriberNotificationTemplateVariables.ts +217 -4
  229. package/Types/StatusPage/SubscriberUpdateNotification.ts +32 -11
  230. package/UI/Components/CustomFields/CustomFieldFormFields.ts +317 -0
  231. package/UI/Components/CustomFields/CustomFieldModelFormFields.tsx +395 -0
  232. package/UI/Components/CustomFields/CustomFieldsDetail.tsx +95 -55
  233. package/UI/Components/Forms/ModelForm.tsx +70 -8
  234. package/UI/Components/Forms/Validation.ts +1 -1
  235. package/UI/Components/ModelFormModal/ModelFormModal.tsx +2 -4
  236. package/UI/Components/ModelTable/AnalyticsModelTable.tsx +2 -6
  237. package/UI/Components/ModelTable/BaseModelTable.tsx +9 -8
  238. package/UI/Components/ModelTable/CustomFieldColumns.tsx +14 -1
  239. package/UI/Components/ModelTable/ModelTable.tsx +6 -7
  240. package/UI/Utils/SensitiveUrlToken.ts +10 -5
  241. package/Utils/API.ts +247 -2
  242. package/Utils/Incident/IncidentNoteTemplateVariables.ts +304 -0
  243. package/Utils/Markdown/MarkdownEscape.ts +65 -0
  244. package/Utils/ProbeNetworkFailureUtil.ts +673 -0
  245. package/build/dist/Models/DatabaseModels/Incident.js +267 -1
  246. package/build/dist/Models/DatabaseModels/Incident.js.map +1 -1
  247. package/build/dist/Models/DatabaseModels/IncidentCustomField.js +207 -1
  248. package/build/dist/Models/DatabaseModels/IncidentCustomField.js.map +1 -1
  249. package/build/dist/Models/DatabaseModels/IncidentEpisode.js +31 -0
  250. package/build/dist/Models/DatabaseModels/IncidentEpisode.js.map +1 -1
  251. package/build/dist/Models/DatabaseModels/IncidentTemplate.js +124 -1
  252. package/build/dist/Models/DatabaseModels/IncidentTemplate.js.map +1 -1
  253. package/build/dist/Models/DatabaseModels/StatusPage.js +56 -0
  254. package/build/dist/Models/DatabaseModels/StatusPage.js.map +1 -1
  255. package/build/dist/Models/DatabaseModels/StatusPageSubscriber.js +131 -0
  256. package/build/dist/Models/DatabaseModels/StatusPageSubscriber.js.map +1 -1
  257. package/build/dist/Server/API/IncidentAPI.js +100 -1
  258. package/build/dist/Server/API/IncidentAPI.js.map +1 -1
  259. package/build/dist/Server/API/StatusPageAPI.js +417 -176
  260. package/build/dist/Server/API/StatusPageAPI.js.map +1 -1
  261. package/build/dist/Server/API/StatusPageSubscriberAPI.js +52 -13
  262. package/build/dist/Server/API/StatusPageSubscriberAPI.js.map +1 -1
  263. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795300000000-SkipHiddenIncidentCreatedNotifications.js +41 -0
  264. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795300000000-SkipHiddenIncidentCreatedNotifications.js.map +1 -0
  265. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795400000000-AddIncidentStatusPageScope.js +57 -0
  266. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795400000000-AddIncidentStatusPageScope.js.map +1 -0
  267. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795500000000-AddIncidentTemplateStatusPageScopeFlag.js +23 -0
  268. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795500000000-AddIncidentTemplateStatusPageScopeFlag.js.map +1 -0
  269. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795600000000-AddStatusPageSubscriberUnsubscribeToken.js +40 -0
  270. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795600000000-AddStatusPageSubscriberUnsubscribeToken.js.map +1 -0
  271. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795700000000-AddStatusPageSubscriberIsAddedByTeam.js +26 -0
  272. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795700000000-AddStatusPageSubscriberIsAddedByTeam.js.map +1 -0
  273. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795800000000-AddIncidentCustomFieldCreateAndNotificationSettings.js +89 -0
  274. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795800000000-AddIncidentCustomFieldCreateAndNotificationSettings.js.map +1 -0
  275. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795900000000-AddSubscriberNotificationClaimedAt.js +29 -0
  276. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1795900000000-AddSubscriberNotificationClaimedAt.js.map +1 -0
  277. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +14 -0
  278. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  279. package/build/dist/Server/Infrastructure/Semaphore.js +3 -0
  280. package/build/dist/Server/Infrastructure/Semaphore.js.map +1 -1
  281. package/build/dist/Server/Middleware/IdentityRateLimit.js +89 -3
  282. package/build/dist/Server/Middleware/IdentityRateLimit.js.map +1 -1
  283. package/build/dist/Server/Middleware/SubscriberNotificationPreviewRateLimit.js +149 -0
  284. package/build/dist/Server/Middleware/SubscriberNotificationPreviewRateLimit.js.map +1 -0
  285. package/build/dist/Server/Middleware/SubscriberNotificationTestSendRateLimit.js +190 -0
  286. package/build/dist/Server/Middleware/SubscriberNotificationTestSendRateLimit.js.map +1 -0
  287. package/build/dist/Server/Services/DatabaseService.js +56 -7
  288. package/build/dist/Server/Services/DatabaseService.js.map +1 -1
  289. package/build/dist/Server/Services/IncidentCustomFieldService.js +204 -8
  290. package/build/dist/Server/Services/IncidentCustomFieldService.js.map +1 -1
  291. package/build/dist/Server/Services/IncidentEpisodePublicNoteService.js +24 -0
  292. package/build/dist/Server/Services/IncidentEpisodePublicNoteService.js.map +1 -1
  293. package/build/dist/Server/Services/IncidentEpisodeService.js +14 -0
  294. package/build/dist/Server/Services/IncidentEpisodeService.js.map +1 -1
  295. package/build/dist/Server/Services/IncidentEpisodeStateTimelineService.js +26 -0
  296. package/build/dist/Server/Services/IncidentEpisodeStateTimelineService.js.map +1 -1
  297. package/build/dist/Server/Services/IncidentPublicNoteService.js +26 -1
  298. package/build/dist/Server/Services/IncidentPublicNoteService.js.map +1 -1
  299. package/build/dist/Server/Services/IncidentService.js +1052 -0
  300. package/build/dist/Server/Services/IncidentService.js.map +1 -1
  301. package/build/dist/Server/Services/IncidentStateTimelineService.js +12 -0
  302. package/build/dist/Server/Services/IncidentStateTimelineService.js.map +1 -1
  303. package/build/dist/Server/Services/IncidentTemplateService.js +83 -0
  304. package/build/dist/Server/Services/IncidentTemplateService.js.map +1 -1
  305. package/build/dist/Server/Services/ScheduledMaintenancePublicNoteService.js +26 -1
  306. package/build/dist/Server/Services/ScheduledMaintenancePublicNoteService.js.map +1 -1
  307. package/build/dist/Server/Services/ScheduledMaintenanceService.js +47 -17
  308. package/build/dist/Server/Services/ScheduledMaintenanceService.js.map +1 -1
  309. package/build/dist/Server/Services/SmsService.js +2 -22
  310. package/build/dist/Server/Services/SmsService.js.map +1 -1
  311. package/build/dist/Server/Services/StatusPageService.js +47 -9
  312. package/build/dist/Server/Services/StatusPageService.js.map +1 -1
  313. package/build/dist/Server/Services/StatusPageSubscriberNotificationTemplateService.js +237 -32
  314. package/build/dist/Server/Services/StatusPageSubscriberNotificationTemplateService.js.map +1 -1
  315. package/build/dist/Server/Services/StatusPageSubscriberNotificationTemplateStatusPageService.js +109 -0
  316. package/build/dist/Server/Services/StatusPageSubscriberNotificationTemplateStatusPageService.js.map +1 -1
  317. package/build/dist/Server/Services/StatusPageSubscriberService.js +925 -99
  318. package/build/dist/Server/Services/StatusPageSubscriberService.js.map +1 -1
  319. package/build/dist/Server/Types/Markdown.js +110 -6
  320. package/build/dist/Server/Types/Markdown.js.map +1 -1
  321. package/build/dist/Server/Types/Workflow/Components/Email.js +55 -6
  322. package/build/dist/Server/Types/Workflow/Components/Email.js.map +1 -1
  323. package/build/dist/Server/Utils/CustomField/CustomFieldRename.js +211 -0
  324. package/build/dist/Server/Utils/CustomField/CustomFieldRename.js.map +1 -0
  325. package/build/dist/Server/Utils/DataSource/EgressGuard.js +41 -12
  326. package/build/dist/Server/Utils/DataSource/EgressGuard.js.map +1 -1
  327. package/build/dist/Server/Utils/Mail/PinnedSmtpSocket.js +101 -0
  328. package/build/dist/Server/Utils/Mail/PinnedSmtpSocket.js.map +1 -0
  329. package/build/dist/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.js +9 -0
  330. package/build/dist/Server/Utils/Monitor/MonitorCriteriaObservationBuilder.js.map +1 -1
  331. package/build/dist/Server/Utils/SSRFProtection.js +48 -6
  332. package/build/dist/Server/Utils/SSRFProtection.js.map +1 -1
  333. package/build/dist/Server/Utils/StatusPage/IncidentStatusPageScope.js +631 -0
  334. package/build/dist/Server/Utils/StatusPage/IncidentStatusPageScope.js.map +1 -0
  335. package/build/dist/Server/Utils/StatusPage/IncidentSubscriberAudienceBuilder.js +403 -0
  336. package/build/dist/Server/Utils/StatusPage/IncidentSubscriberAudienceBuilder.js.map +1 -0
  337. package/build/dist/Server/Utils/StatusPage/IncidentTemplateVariableBuilder.js +451 -0
  338. package/build/dist/Server/Utils/StatusPage/IncidentTemplateVariableBuilder.js.map +1 -0
  339. package/build/dist/Server/Utils/StatusPage/StatusPageExclusion.js +13 -0
  340. package/build/dist/Server/Utils/StatusPage/StatusPageExclusion.js.map +1 -0
  341. package/build/dist/Server/Utils/StatusPage/StatusPageReadAccess.js +91 -0
  342. package/build/dist/Server/Utils/StatusPage/StatusPageReadAccess.js.map +1 -0
  343. package/build/dist/Server/Utils/StatusPage/StatusPageSubscriberUnsubscribeNotice.js +101 -0
  344. package/build/dist/Server/Utils/StatusPage/StatusPageSubscriberUnsubscribeNotice.js.map +1 -0
  345. package/build/dist/Server/Utils/StatusPage/StatusPageSubscriberUnsubscribeToken.js +47 -0
  346. package/build/dist/Server/Utils/StatusPage/StatusPageSubscriberUnsubscribeToken.js.map +1 -0
  347. package/build/dist/Server/Utils/StatusPage/SubscriberIncidentEmailBuilder.js +273 -0
  348. package/build/dist/Server/Utils/StatusPage/SubscriberIncidentEmailBuilder.js.map +1 -0
  349. package/build/dist/Server/Utils/StatusPage/SubscriberNotificationClaim.js +73 -0
  350. package/build/dist/Server/Utils/StatusPage/SubscriberNotificationClaim.js.map +1 -0
  351. package/build/dist/Server/Utils/StatusPage/SubscriberNotificationDeliveryRecord.js +722 -0
  352. package/build/dist/Server/Utils/StatusPage/SubscriberNotificationDeliveryRecord.js.map +1 -0
  353. package/build/dist/Server/Utils/StatusPage/SubscriberNotificationFanOut.js +102 -0
  354. package/build/dist/Server/Utils/StatusPage/SubscriberNotificationFanOut.js.map +1 -0
  355. package/build/dist/Server/Utils/StatusPage/SubscriberNotificationPreviewBuilder.js +527 -0
  356. package/build/dist/Server/Utils/StatusPage/SubscriberNotificationPreviewBuilder.js.map +1 -0
  357. package/build/dist/Server/Utils/StatusPage/SubscriberNotificationResendAccess.js +278 -0
  358. package/build/dist/Server/Utils/StatusPage/SubscriberNotificationResendAccess.js.map +1 -0
  359. package/build/dist/Server/Utils/StatusPage/SubscriberNotificationRunLimit.js +137 -0
  360. package/build/dist/Server/Utils/StatusPage/SubscriberNotificationRunLimit.js.map +1 -0
  361. package/build/dist/Server/Utils/StatusPage/SubscriberNotificationTiming.js +103 -0
  362. package/build/dist/Server/Utils/StatusPage/SubscriberNotificationTiming.js.map +1 -0
  363. package/build/dist/Server/Utils/StatusPage/SubscriberTemplateIncidentRecordAccess.js +114 -0
  364. package/build/dist/Server/Utils/StatusPage/SubscriberTemplateIncidentRecordAccess.js.map +1 -0
  365. package/build/dist/Server/Utils/StatusPageResource.js +39 -7
  366. package/build/dist/Server/Utils/StatusPageResource.js.map +1 -1
  367. package/build/dist/Server/Utils/VM/VMAPI.js.map +1 -1
  368. package/build/dist/Server/Utils/VM/VMRunner.js +1 -0
  369. package/build/dist/Server/Utils/VM/VMRunner.js.map +1 -1
  370. package/build/dist/Server/Utils/Workflow/OAuth2TokenClient.js +3 -0
  371. package/build/dist/Server/Utils/Workflow/OAuth2TokenClient.js.map +1 -1
  372. package/build/dist/Types/CustomField/CustomFieldOrder.js +36 -0
  373. package/build/dist/Types/CustomField/CustomFieldOrder.js.map +1 -0
  374. package/build/dist/Types/CustomField/CustomFieldSavedViews.js +135 -0
  375. package/build/dist/Types/CustomField/CustomFieldSavedViews.js.map +1 -0
  376. package/build/dist/Types/CustomField/CustomFieldTemplateMerge.js +27 -0
  377. package/build/dist/Types/CustomField/CustomFieldTemplateMerge.js.map +1 -0
  378. package/build/dist/Types/CustomField/CustomFieldType.js +12 -0
  379. package/build/dist/Types/CustomField/CustomFieldType.js.map +1 -1
  380. package/build/dist/Types/CustomField/CustomFieldValueFormat.js +126 -0
  381. package/build/dist/Types/CustomField/CustomFieldValueFormat.js.map +1 -0
  382. package/build/dist/Types/CustomField/CustomFieldValueValidator.js +280 -0
  383. package/build/dist/Types/CustomField/CustomFieldValueValidator.js.map +1 -0
  384. package/build/dist/Types/CustomField/CustomFieldVariableKey.js +150 -0
  385. package/build/dist/Types/CustomField/CustomFieldVariableKey.js.map +1 -0
  386. package/build/dist/Types/SafeHtml.js +84 -0
  387. package/build/dist/Types/SafeHtml.js.map +1 -0
  388. package/build/dist/Types/StatusPage/IncidentCreatedRenotify.js +117 -0
  389. package/build/dist/Types/StatusPage/IncidentCreatedRenotify.js.map +1 -0
  390. package/build/dist/Types/StatusPage/IncidentCreatedResend.js +86 -0
  391. package/build/dist/Types/StatusPage/IncidentCreatedResend.js.map +1 -0
  392. package/build/dist/Types/StatusPage/IncidentScopeAddedPagesNotification.js +246 -0
  393. package/build/dist/Types/StatusPage/IncidentScopeAddedPagesNotification.js.map +1 -0
  394. package/build/dist/Types/StatusPage/IncidentSubscriberAudience.js +183 -0
  395. package/build/dist/Types/StatusPage/IncidentSubscriberAudience.js.map +1 -0
  396. package/build/dist/Types/StatusPage/StatusPageSubscriberUnsubscribe.js +277 -0
  397. package/build/dist/Types/StatusPage/StatusPageSubscriberUnsubscribe.js.map +1 -0
  398. package/build/dist/Types/StatusPage/SubscriberNotificationInterruption.js +27 -0
  399. package/build/dist/Types/StatusPage/SubscriberNotificationInterruption.js.map +1 -0
  400. package/build/dist/Types/StatusPage/SubscriberNotificationPreview.js +190 -0
  401. package/build/dist/Types/StatusPage/SubscriberNotificationPreview.js.map +1 -0
  402. package/build/dist/Types/StatusPage/SubscriberNotificationResend.js +102 -0
  403. package/build/dist/Types/StatusPage/SubscriberNotificationResend.js.map +1 -0
  404. package/build/dist/Types/StatusPage/SubscriberNotificationTemplateCompiler.js +97 -0
  405. package/build/dist/Types/StatusPage/SubscriberNotificationTemplateCompiler.js.map +1 -0
  406. package/build/dist/Types/StatusPage/SubscriberNotificationTemplatePreview.js +175 -0
  407. package/build/dist/Types/StatusPage/SubscriberNotificationTemplatePreview.js.map +1 -0
  408. package/build/dist/Types/StatusPage/SubscriberNotificationTemplateVariables.js +144 -4
  409. package/build/dist/Types/StatusPage/SubscriberNotificationTemplateVariables.js.map +1 -1
  410. package/build/dist/Types/StatusPage/SubscriberUpdateNotification.js +29 -9
  411. package/build/dist/Types/StatusPage/SubscriberUpdateNotification.js.map +1 -1
  412. package/build/dist/UI/Components/CustomFields/CustomFieldFormFields.js +169 -0
  413. package/build/dist/UI/Components/CustomFields/CustomFieldFormFields.js.map +1 -0
  414. package/build/dist/UI/Components/CustomFields/CustomFieldModelFormFields.js +212 -0
  415. package/build/dist/UI/Components/CustomFields/CustomFieldModelFormFields.js.map +1 -0
  416. package/build/dist/UI/Components/CustomFields/CustomFieldsDetail.js +64 -49
  417. package/build/dist/UI/Components/CustomFields/CustomFieldsDetail.js.map +1 -1
  418. package/build/dist/UI/Components/Forms/ModelForm.js +39 -5
  419. package/build/dist/UI/Components/Forms/ModelForm.js.map +1 -1
  420. package/build/dist/UI/Components/Forms/Validation.js +1 -1
  421. package/build/dist/UI/Components/Forms/Validation.js.map +1 -1
  422. package/build/dist/UI/Components/ModelFormModal/ModelFormModal.js.map +1 -1
  423. package/build/dist/UI/Components/ModelTable/AnalyticsModelTable.js.map +1 -1
  424. package/build/dist/UI/Components/ModelTable/BaseModelTable.js +2 -2
  425. package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
  426. package/build/dist/UI/Components/ModelTable/CustomFieldColumns.js +13 -1
  427. package/build/dist/UI/Components/ModelTable/CustomFieldColumns.js.map +1 -1
  428. package/build/dist/UI/Components/ModelTable/ModelTable.js +1 -1
  429. package/build/dist/UI/Components/ModelTable/ModelTable.js.map +1 -1
  430. package/build/dist/UI/Utils/SensitiveUrlToken.js +10 -5
  431. package/build/dist/UI/Utils/SensitiveUrlToken.js.map +1 -1
  432. package/build/dist/Utils/API.js +177 -1
  433. package/build/dist/Utils/API.js.map +1 -1
  434. package/build/dist/Utils/Incident/IncidentNoteTemplateVariables.js +155 -0
  435. package/build/dist/Utils/Incident/IncidentNoteTemplateVariables.js.map +1 -0
  436. package/build/dist/Utils/Markdown/MarkdownEscape.js +48 -0
  437. package/build/dist/Utils/Markdown/MarkdownEscape.js.map +1 -1
  438. package/build/dist/Utils/ProbeNetworkFailureUtil.js +460 -0
  439. package/build/dist/Utils/ProbeNetworkFailureUtil.js.map +1 -0
  440. package/package.json +1 -1
@@ -0,0 +1,101 @@
1
+ import Markdown from "../../Types/Markdown";
2
+ import OneUptimeDate from "../../../Types/Date";
3
+ import { StatusPageSubscriberUnsubscribeChannel, } from "../../../Types/StatusPage/StatusPageSubscriberUnsubscribe";
4
+ /*
5
+ * The email a status page's team gets when a subscriber the team added
6
+ * unsubscribes itself.
7
+ *
8
+ * Anyone who can read a mailbox can unsubscribe it. For an address somebody
9
+ * signed up themselves that is the point; for one the team added - a site's
10
+ * mailing list, say site03-all@ - it means one reader can take a whole site
11
+ * off the page before the next outage, and nobody would notice until then. So
12
+ * when a subscriber the team added (StatusPageSubscriber.isAddedByTeam: from
13
+ * the dashboard, with an API key or by a workflow, never a sign-up on the
14
+ * status page) unsubscribes through its link or the manage page, the page's
15
+ * owners and the teammate who added it, if a teammate did, are told
16
+ * (StatusPageSubscriberService.notifyTeamOfUnsubscribe). Without a teammate -
17
+ * an API key or a workflow added it - the email says someone on the team did.
18
+ *
19
+ * Kept free of database access so what the email says can be pinned by a
20
+ * test. It is sent through the SimpleMessage template, whose `message` is
21
+ * inserted as HTML, so every value from a subscriber or a teammate is escaped
22
+ * here.
23
+ */
24
+ // How the subscription was cancelled, which the email names.
25
+ export var StatusPageSubscriberUnsubscribeSource;
26
+ (function (StatusPageSubscriberUnsubscribeSource) {
27
+ // The link at the bottom of a notification (the status page's unsubscribe page).
28
+ StatusPageSubscriberUnsubscribeSource["UnsubscribeLink"] = "UnsubscribeLink";
29
+ // The Update Subscription page, where a subscriber can also change preferences.
30
+ StatusPageSubscriberUnsubscribeSource["ManageSubscriptionPage"] = "ManageSubscriptionPage";
31
+ })(StatusPageSubscriberUnsubscribeSource || (StatusPageSubscriberUnsubscribeSource = {}));
32
+ const SUBSCRIBER_LIST_ROUTES = {
33
+ [StatusPageSubscriberUnsubscribeChannel.Email]: "email-subscribers",
34
+ [StatusPageSubscriberUnsubscribeChannel.SMS]: "sms-subscribers",
35
+ [StatusPageSubscriberUnsubscribeChannel.Slack]: "slack-subscribers",
36
+ [StatusPageSubscriberUnsubscribeChannel.MicrosoftTeams]: "microsoft-teams-subscribers",
37
+ [StatusPageSubscriberUnsubscribeChannel.Webhook]: "webhook-subscribers",
38
+ };
39
+ const CHANNEL_NAMES = {
40
+ [StatusPageSubscriberUnsubscribeChannel.Email]: "email subscriber",
41
+ [StatusPageSubscriberUnsubscribeChannel.SMS]: "SMS subscriber",
42
+ [StatusPageSubscriberUnsubscribeChannel.Slack]: "Slack subscriber",
43
+ [StatusPageSubscriberUnsubscribeChannel.MicrosoftTeams]: "Microsoft Teams subscriber",
44
+ [StatusPageSubscriberUnsubscribeChannel.Webhook]: "webhook subscriber",
45
+ };
46
+ class StatusPageSubscriberUnsubscribeNotice {
47
+ /*
48
+ * The dashboard route, under the status page, of the list a channel's
49
+ * subscribers are on (Dashboard RouteMap, STATUS_PAGE_VIEW_*_SUBSCRIBERS).
50
+ */
51
+ static getSubscriberListRoute(channel) {
52
+ return SUBSCRIBER_LIST_ROUTES[channel];
53
+ }
54
+ static build(input) {
55
+ var _a;
56
+ const escape = Markdown.escapeHtml;
57
+ const channelName = CHANNEL_NAMES[input.contact.channel];
58
+ const contact = input.contact.contact.trim();
59
+ const who = contact
60
+ ? `The ${channelName} <strong>${escape(contact)}</strong>`
61
+ : `A ${channelName}`;
62
+ const how = input.source === StatusPageSubscriberUnsubscribeSource.UnsubscribeLink
63
+ ? "using the unsubscribe link in a notification"
64
+ : "on the status page's Update Subscription page";
65
+ const addedBy = ((_a = input.addedByName) === null || _a === void 0 ? void 0 : _a.trim())
66
+ ? escape(input.addedByName.trim())
67
+ : "Someone on your team";
68
+ const addedOn = input.addedAt
69
+ ? ` on ${escape(StatusPageSubscriberUnsubscribeNotice.formatDate(input.addedAt))}`
70
+ : "";
71
+ const statusPageName = escape(input.statusPageName);
72
+ const subscriberListUrl = escape(input.subscriberListUrl);
73
+ const message = [
74
+ `<p>${who} unsubscribed from the status page <strong>${statusPageName}</strong> ${how}, at ${escape(StatusPageSubscriberUnsubscribeNotice.formatDate(input.unsubscribedAt))}. It will not receive this page's notifications any more.</p>`,
75
+ `<p>${addedBy} added this subscriber${addedOn}. Anyone who reads a shared address, such as a mailing list, can unsubscribe it for everyone who reads it. If that is what happened, add it back or add the people who still need these notifications.</p>`,
76
+ `<p>You are receiving this because you own this status page or added this subscriber. <a href="${subscriberListUrl}">View the status page's subscribers</a>.</p>`,
77
+ ].join("");
78
+ return {
79
+ subject: `A subscriber your team added unsubscribed from ${input.statusPageName}`,
80
+ message: message,
81
+ };
82
+ }
83
+ static formatDate(date) {
84
+ return OneUptimeDate.getDateAsFormattedStringInTimezone({
85
+ date: date,
86
+ timezone: "UTC",
87
+ use12HourFormat: false,
88
+ });
89
+ }
90
+ }
91
+ /*
92
+ * The team is told about one subscriber unsubscribing at most once in this
93
+ * many hours (StatusPageSubscriberService.notifyTeamOfUnsubscribe): the
94
+ * public manage page can re-subscribe and cancel a subscription over and
95
+ * over, and each cancellation would otherwise email every owner.
96
+ */
97
+ StatusPageSubscriberUnsubscribeNotice.noticeWindowInHours = 24;
98
+ // Where the time of each subscriber's last notice is kept.
99
+ StatusPageSubscriberUnsubscribeNotice.noticeCacheNamespace = "status-page-subscriber-unsubscribe-notice";
100
+ export default StatusPageSubscriberUnsubscribeNotice;
101
+ //# sourceMappingURL=StatusPageSubscriberUnsubscribeNotice.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StatusPageSubscriberUnsubscribeNotice.js","sourceRoot":"","sources":["../../../../../Server/Utils/StatusPage/StatusPageSubscriberUnsubscribeNotice.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,47 @@
1
+ import StatusPageSubscriberUnsubscribe from "../../../Types/StatusPage/StatusPageSubscriberUnsubscribe";
2
+ import crypto from "crypto";
3
+ /*
4
+ * The secret half of a status page subscriber's unsubscribe link
5
+ * (StatusPageSubscriber.unsubscribeToken; the link itself is built by
6
+ * Common/Types/StatusPage/StatusPageSubscriberUnsubscribe).
7
+ *
8
+ * Server-only on purpose, like VerificationCode: a token is minted from
9
+ * Node's CSPRNG and nothing here falls back to Math.random. If the platform
10
+ * cannot produce secure randomness, generation throws and the subscriber is
11
+ * not created, rather than being given a guessable link.
12
+ *
13
+ * It is not the six-digit subscriptionConfirmationToken. That one only has to
14
+ * survive the few minutes until an address confirms, and a million guesses
15
+ * cover it; this one stays valid for as long as the subscription does.
16
+ */
17
+ /*
18
+ * What a presented token is compared against when there is nothing real to
19
+ * compare it with - no subscriber, no stored token, or a malformed value - so
20
+ * that a refusal costs the same full-length comparison as a wrong token.
21
+ */
22
+ const COMPARISON_PLACEHOLDER = "0".repeat(StatusPageSubscriberUnsubscribe.TOKEN_LENGTH);
23
+ export default class StatusPageSubscriberUnsubscribeToken {
24
+ // 32 random bytes as 64 lowercase hex characters, the pattern of PasswordHash.generateSalt.
25
+ static generate() {
26
+ return crypto.randomBytes(32).toString("hex");
27
+ }
28
+ /*
29
+ * Whether the token from a link is the subscription's token.
30
+ *
31
+ * Constant time: `===` stops at the first differing character, which would
32
+ * tell someone guessing how much of a guess was right. Both sides are
33
+ * well-formed 64-character strings by the time they reach timingSafeEqual
34
+ * (which throws on a length mismatch); anything else is swapped for a
35
+ * placeholder of the same length first and the answer is false regardless,
36
+ * so a missing subscriber, a missing stored token and a wrong token all
37
+ * take the same path.
38
+ */
39
+ static matches(data) {
40
+ const presented = typeof data.presented === "string" ? data.presented.toLowerCase() : "";
41
+ const storedIsUsable = StatusPageSubscriberUnsubscribe.isWellFormedToken(data.stored);
42
+ const presentedIsUsable = StatusPageSubscriberUnsubscribe.isWellFormedToken(presented);
43
+ const isEqual = crypto.timingSafeEqual(Buffer.from(storedIsUsable ? data.stored : COMPARISON_PLACEHOLDER, "utf8"), Buffer.from(presentedIsUsable ? presented : COMPARISON_PLACEHOLDER, "utf8"));
44
+ return storedIsUsable && presentedIsUsable && isEqual;
45
+ }
46
+ }
47
+ //# sourceMappingURL=StatusPageSubscriberUnsubscribeToken.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StatusPageSubscriberUnsubscribeToken.js","sourceRoot":"","sources":["../../../../../Server/Utils/StatusPage/StatusPageSubscriberUnsubscribeToken.ts"],"names":[],"mappings":"AAAA,OAAO,+BAA+B,MAAM,2DAA2D,CAAC;AACxG,OAAO,MAAM,MAAM,QAAQ,CAAC;AAE5B;;;;;;;;;;;;;GAaG;AAEH;;;;GAIG;AACH,MAAM,sBAAsB,GAAW,GAAG,CAAC,MAAM,CAC/C,+BAA+B,CAAC,YAAY,CAC7C,CAAC;AAEF,MAAM,CAAC,OAAO,OAAO,oCAAoC;IACvD,4FAA4F;IACrF,MAAM,CAAC,QAAQ;QACpB,OAAO,MAAM,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAChD,CAAC;IAED;;;;;;;;;;OAUG;IACI,MAAM,CAAC,OAAO,CAAC,IAGrB;QACC,MAAM,SAAS,GACb,OAAO,IAAI,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAEzE,MAAM,cAAc,GAClB,+BAA+B,CAAC,iBAAiB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACjE,MAAM,iBAAiB,GACrB,+BAA+B,CAAC,iBAAiB,CAAC,SAAS,CAAC,CAAC;QAE/D,MAAM,OAAO,GAAY,MAAM,CAAC,eAAe,CAC7C,MAAM,CAAC,IAAI,CACT,cAAc,CAAC,CAAC,CAAE,IAAI,CAAC,MAAiB,CAAC,CAAC,CAAC,sBAAsB,EACjE,MAAM,CACP,EACD,MAAM,CAAC,IAAI,CACT,iBAAiB,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,sBAAsB,EACtD,MAAM,CACP,CACF,CAAC;QAEF,OAAO,cAAc,IAAI,iBAAiB,IAAI,OAAO,CAAC;IACxD,CAAC;CACF"}
@@ -0,0 +1,273 @@
1
+ import { StatusPageApiRoute } from "../../../ServiceRoute";
2
+ import URL from "../../../Types/API/URL";
3
+ import OneUptimeDate from "../../../Types/Date";
4
+ import EmailTemplateType from "../../../Types/Email/EmailTemplateType";
5
+ import BadDataException from "../../../Types/Exception/BadDataException";
6
+ import StatusPageSubscriberNotificationEventType from "../../../Types/StatusPage/StatusPageSubscriberNotificationEventType";
7
+ import StatusPageSubscriberNotificationMethod from "../../../Types/StatusPage/StatusPageSubscriberNotificationMethod";
8
+ import { SubscriberEmailTemplateChoiceReason, } from "../../../Types/StatusPage/SubscriberNotificationPreview";
9
+ import { Service as StatusPageServiceType } from "../../Services/StatusPageService";
10
+ import StatusPageSubscriberNotificationTemplateService, { Service as StatusPageSubscriberNotificationTemplateServiceClass, } from "../../Services/StatusPageSubscriberNotificationTemplateService";
11
+ import IncidentTemplateVariableBuilder from "./IncidentTemplateVariableBuilder";
12
+ /*
13
+ * The email a status page's subscribers get about an incident - its subject
14
+ * and its body, from the page's custom template or the default one - for the
15
+ * 'incident created' and public note (posted and updated) notifications.
16
+ *
17
+ * The one code path for it. The subscriber jobs send what this builds
18
+ * (Workers/Jobs/Incident/SendNotificationToSubscribers and
19
+ * Workers/Jobs/IncidentPublicNote/SendNotificationToSubscribers), and "Preview
20
+ * notification" and "Send test to me" show and send the same thing
21
+ * (Notification/API/SubscriberNotificationPreview), rendered by the same
22
+ * mailer (Notification MailService.render). A preview therefore cannot show
23
+ * one email while subscribers are sent another.
24
+ *
25
+ * It builds on what the jobs already share, rather than repeating it:
26
+ *
27
+ * - IncidentTemplateVariableBuilder for the values, in each channel's
28
+ * format (buildTemplateVariables reads them for an event), and
29
+ * - SubscriberNotificationTemplateCompiler, through the template service,
30
+ * for a custom template: compileEmailBodyTemplate for the body, which
31
+ * escapes every plain value, and compileTemplate for the subject.
32
+ *
33
+ * The page's custom email template is used only when it has a body and the
34
+ * page sends through its own SMTP server, as the jobs have always done;
35
+ * templateChoice says which email the page's subscribers get, and why.
36
+ *
37
+ * Building an email has no side effects. Sending one does: the custom field
38
+ * values it carries are recorded for the incident feed, and a Rich text
39
+ * field's inline images are made public so the recipient can load them. So a
40
+ * job calls recordSending before each message goes out, and a preview never
41
+ * does - previewing an email must not publish anything.
42
+ */
43
+ // Which notification the email is for.
44
+ export var SubscriberIncidentEmailEvent;
45
+ (function (SubscriberIncidentEmailEvent) {
46
+ SubscriberIncidentEmailEvent["IncidentCreated"] = "IncidentCreated";
47
+ SubscriberIncidentEmailEvent["IncidentPublicNoteCreated"] = "IncidentPublicNoteCreated";
48
+ SubscriberIncidentEmailEvent["IncidentPublicNoteUpdated"] = "IncidentPublicNoteUpdated";
49
+ })(SubscriberIncidentEmailEvent || (SubscriberIncidentEmailEvent = {}));
50
+ const EMAIL_COPY = {
51
+ [SubscriberIncidentEmailEvent.IncidentCreated]: {
52
+ templateEventType: StatusPageSubscriberNotificationEventType.SubscriberIncidentCreated,
53
+ defaultTemplateType: EmailTemplateType.SubscriberIncidentCreated,
54
+ defaultSubjectPrefix: "[Incident] ",
55
+ customTemplateSubjectPrefix: "[Incident] ",
56
+ },
57
+ [SubscriberIncidentEmailEvent.IncidentPublicNoteCreated]: {
58
+ templateEventType: StatusPageSubscriberNotificationEventType.SubscriberIncidentNoteCreated,
59
+ defaultTemplateType: EmailTemplateType.SubscriberIncidentNoteCreated,
60
+ defaultSubjectPrefix: "[Update Incident] ",
61
+ customTemplateSubjectPrefix: "[Incident Update] ",
62
+ },
63
+ [SubscriberIncidentEmailEvent.IncidentPublicNoteUpdated]: {
64
+ templateEventType: StatusPageSubscriberNotificationEventType.SubscriberIncidentNoteUpdated,
65
+ defaultTemplateType: EmailTemplateType.SubscriberIncidentNoteUpdated,
66
+ defaultSubjectPrefix: "[Incident Note Updated] ",
67
+ customTemplateSubjectPrefix: "[Incident Note Updated] ",
68
+ },
69
+ };
70
+ export default class SubscriberIncidentEmailBuilder {
71
+ /**
72
+ * The values every message of this event is filled with, on every
73
+ * channel, read once per send (IncidentTemplateVariableBuilder).
74
+ *
75
+ * The incident needs projectId, title, incidentSeverity.name, labels.name
76
+ * and customFields; a public note's also currentIncidentState.name.
77
+ * statusPages are the pages the send reaches, which name
78
+ * {{affectedStatusPages}}. A public note's event takes the note and when
79
+ * it says it was posted - an update reads it fresh from the row, and only a
80
+ * note with none falls back to now.
81
+ */
82
+ static async buildTemplateVariables(data) {
83
+ var _a, _b, _c;
84
+ if (data.event === SubscriberIncidentEmailEvent.IncidentCreated) {
85
+ return IncidentTemplateVariableBuilder.build({
86
+ incident: data.incident,
87
+ statusPages: data.statusPages,
88
+ markdownVariables: {
89
+ incidentDescription: data.incident.description,
90
+ },
91
+ });
92
+ }
93
+ return IncidentTemplateVariableBuilder.build({
94
+ incident: data.incident,
95
+ statusPages: data.statusPages,
96
+ markdownVariables: {
97
+ note: (_a = data.note) === null || _a === void 0 ? void 0 : _a.text,
98
+ },
99
+ textVariables: {
100
+ incidentState: ((_b = data.incident.currentIncidentState) === null || _b === void 0 ? void 0 : _b.name) || "",
101
+ postedAt: OneUptimeDate.getDateAsUserFriendlyFormattedString(((_c = data.note) === null || _c === void 0 ? void 0 : _c.postedAt) || OneUptimeDate.getCurrentDate()),
102
+ },
103
+ });
104
+ }
105
+ /*
106
+ * The incident on the status page, or the status page itself for an
107
+ * incident that has no id yet (one being previewed before it is declared).
108
+ */
109
+ static getDetailsUrl(data) {
110
+ return data.incidentId && data.statusPageUrl
111
+ ? URL.fromString(data.statusPageUrl)
112
+ .addRoute(`/incidents/${data.incidentId.toString()}`)
113
+ .toString()
114
+ : data.statusPageUrl;
115
+ }
116
+ // The status page's logo, for the default email, or "" when it has none.
117
+ static getLogoUrl(data) {
118
+ var _a, _b;
119
+ const statusPageId = ((_a = data.statusPage.id) === null || _a === void 0 ? void 0 : _a.toString()) || ((_b = data.statusPage._id) === null || _b === void 0 ? void 0 : _b.toString()) || null;
120
+ return data.statusPage.logoFileId && statusPageId
121
+ ? new URL(data.httpProtocol, data.host)
122
+ .addRoute(StatusPageApiRoute)
123
+ .addRoute(`/logo/${statusPageId}`)
124
+ .toString()
125
+ : "";
126
+ }
127
+ /*
128
+ * Which email a page's subscribers get: its custom template only when the
129
+ * template has a body and the page sends through its own SMTP server.
130
+ */
131
+ static chooseTemplate(data) {
132
+ var _a;
133
+ const customTemplateName = ((_a = data.emailTemplate) === null || _a === void 0 ? void 0 : _a.templateName) || undefined;
134
+ if (!data.emailTemplate) {
135
+ return {
136
+ usesCustomTemplate: false,
137
+ reason: SubscriberEmailTemplateChoiceReason.NoCustomTemplate,
138
+ };
139
+ }
140
+ if (!data.emailTemplate.templateBody) {
141
+ return {
142
+ usesCustomTemplate: false,
143
+ reason: SubscriberEmailTemplateChoiceReason.CustomTemplateIsEmpty,
144
+ customTemplateName: customTemplateName,
145
+ };
146
+ }
147
+ if (!data.statusPage.smtpConfig) {
148
+ return {
149
+ usesCustomTemplate: false,
150
+ reason: SubscriberEmailTemplateChoiceReason.CustomTemplateNeedsCustomSmtp,
151
+ customTemplateName: customTemplateName,
152
+ };
153
+ }
154
+ return {
155
+ usesCustomTemplate: true,
156
+ reason: SubscriberEmailTemplateChoiceReason.CustomTemplate,
157
+ customTemplateName: customTemplateName,
158
+ };
159
+ }
160
+ /**
161
+ * One status page's email for this event. Looks up the page's custom
162
+ * email template for the event; everything else comes in: the values
163
+ * (buildTemplateVariables, then forStatusPage for this page), the page's
164
+ * URL and the incident's details URL on it (getDetailsUrl), and the
165
+ * instance's host and protocol for the logo.
166
+ *
167
+ * The page needs what StatusPageSubscriberService.
168
+ * getStatusPagesToSendNotification reads: its names, logoFileId,
169
+ * isPublicStatusPage, smtpConfig and the footer text columns.
170
+ */
171
+ static async forStatusPage(data) {
172
+ var _a;
173
+ const copy = EMAIL_COPY[data.event];
174
+ const statusPage = data.statusPage;
175
+ const incidentTemplateVariables = data.incidentTemplateVariables;
176
+ const pageTemplateVariables = data.pageTemplateVariables;
177
+ const incidentTitle = data.incident.title || "";
178
+ if (!statusPage.id) {
179
+ throw new BadDataException("Cannot build a status page's subscriber email without its id.");
180
+ }
181
+ const emailTemplate = await StatusPageSubscriberNotificationTemplateService.getTemplateForStatusPage({
182
+ statusPageId: statusPage.id,
183
+ eventType: copy.templateEventType,
184
+ notificationMethod: StatusPageSubscriberNotificationMethod.Email,
185
+ });
186
+ const templateChoice = this.chooseTemplate({
187
+ emailTemplate: emailTemplate,
188
+ statusPage: statusPage,
189
+ });
190
+ if (templateChoice.usesCustomTemplate) {
191
+ return {
192
+ templateChoice: templateChoice,
193
+ forSubscriber: (subscriber) => {
194
+ /*
195
+ * The body is HTML (BlankTemplate wraps nothing around it), so its
196
+ * plain values are escaped; the subject is text, and gets them as
197
+ * written.
198
+ */
199
+ const emailBodyTemplateVariables = Object.assign(Object.assign({}, pageTemplateVariables.emailBody), { unsubscribeUrl: subscriber.unsubscribeUrl });
200
+ const plainTextTemplateVariables = Object.assign(Object.assign({}, pageTemplateVariables.plainText), { unsubscribeUrl: subscriber.unsubscribeUrl });
201
+ const compiledBody = StatusPageSubscriberNotificationTemplateServiceClass.compileEmailBodyTemplate(emailTemplate.templateBody, emailBodyTemplateVariables);
202
+ const compiledSubject = emailTemplate.emailSubject
203
+ ? StatusPageSubscriberNotificationTemplateServiceClass.compileTemplate(emailTemplate.emailSubject, plainTextTemplateVariables)
204
+ : copy.customTemplateSubjectPrefix + incidentTitle;
205
+ return {
206
+ subject: compiledSubject,
207
+ envelope: {
208
+ templateType: EmailTemplateType.BlankTemplate,
209
+ vars: {
210
+ body: compiledBody,
211
+ },
212
+ subject: compiledSubject,
213
+ isSubjectLiteral: true,
214
+ },
215
+ };
216
+ },
217
+ recordSending: async () => {
218
+ await incidentTemplateVariables.recordFieldsUsedBy([
219
+ emailTemplate.templateBody,
220
+ emailTemplate.emailSubject,
221
+ ]);
222
+ },
223
+ };
224
+ }
225
+ const subject = copy.defaultSubjectPrefix + incidentTitle;
226
+ // What the default email reads that does not vary per subscriber.
227
+ const pageVars = {
228
+ statusPageName: IncidentTemplateVariableBuilder.getStatusPageName(statusPage),
229
+ statusPageUrl: data.statusPageUrl,
230
+ detailsUrl: data.detailsUrl,
231
+ logoUrl: this.getLogoUrl({
232
+ statusPage: statusPage,
233
+ host: data.host,
234
+ httpProtocol: data.httpProtocol,
235
+ }),
236
+ isPublicStatusPage: statusPage.isPublicStatusPage ? "true" : "false",
237
+ // Every name escaped, "<br/>" between groups: for the raw slot.
238
+ resourcesAffected: pageTemplateVariables.resourcesAffectedHtml,
239
+ incidentSeverity: ((_a = data.incident.incidentSeverity) === null || _a === void 0 ? void 0 : _a.name) || " - ",
240
+ incidentTitle: incidentTitle,
241
+ // The fields marked "Include in Subscriber Notifications".
242
+ customFieldRows: pageTemplateVariables.customFieldRows,
243
+ subscriberEmailNotificationFooterText: StatusPageServiceType.getSubscriberEmailFooterText(statusPage),
244
+ };
245
+ // The event's own content, rendered from Markdown once per send.
246
+ if (data.event === SubscriberIncidentEmailEvent.IncidentCreated) {
247
+ pageVars["incidentDescription"] =
248
+ incidentTemplateVariables.getMarkdownVariable("incidentDescription").html;
249
+ }
250
+ else {
251
+ pageVars["note"] =
252
+ incidentTemplateVariables.getMarkdownVariable("note").html;
253
+ }
254
+ return {
255
+ templateChoice: templateChoice,
256
+ forSubscriber: (subscriber) => {
257
+ return {
258
+ subject: subject,
259
+ envelope: {
260
+ templateType: copy.defaultTemplateType,
261
+ vars: Object.assign(Object.assign({}, pageVars), { unsubscribeUrl: subscriber.unsubscribeUrl }),
262
+ subject: subject,
263
+ isSubjectLiteral: true,
264
+ },
265
+ };
266
+ },
267
+ recordSending: async () => {
268
+ await incidentTemplateVariables.recordIncludedFieldsSent();
269
+ },
270
+ };
271
+ }
272
+ }
273
+ //# sourceMappingURL=SubscriberIncidentEmailBuilder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SubscriberIncidentEmailBuilder.js","sourceRoot":"","sources":["../../../../../Server/Utils/StatusPage/SubscriberIncidentEmailBuilder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,73 @@
1
+ import OneUptimeDate from "../../../Types/Date";
2
+ import StatusPageSubscriberNotificationStatus from "../../../Types/StatusPage/StatusPageSubscriberNotificationStatus";
3
+ /*
4
+ * The two writes that move a subscriber notification in and out of
5
+ * InProgress without racing anyone: a job claiming a Pending notification to
6
+ * send it, and the sweeper failing one whose send was interrupted.
7
+ *
8
+ * Why a claim. The subscriber jobs run every minute, and a run can now take
9
+ * as long as its sends (SubscriberNotificationTiming), so the next run starts
10
+ * while the last is still going - on another worker slot, or another worker.
11
+ * Each run reads the Pending notifications when it starts. Without a claim,
12
+ * a run still working through its list would send a notification a later run
13
+ * had already sent, or pick up one that was re-queued since it read it and
14
+ * send it with what it read before (for the incident created notification,
15
+ * an old record of the pages already told, so those pages would be told
16
+ * again).
17
+ *
18
+ * A claim is one conditional UPDATE: Pending to InProgress, only if the row
19
+ * is still Pending and its version is still the one the job read. Every
20
+ * write through the services bumps the version, so a notification that was
21
+ * sent, re-queued or edited since is left for a run that reads it afresh.
22
+ * Exactly one run wins a notification. The claim is a hook-free write: it
23
+ * fires none of the row's 'on update' workflows, realtime events or audit
24
+ * log entries (the status the send settles on does). It stamps updatedAt,
25
+ * and, for a notification with one, its claimed-at column: the sweeper times
26
+ * an InProgress row from the claimed-at column where there is one, since
27
+ * other code writes those rows (an open incident or episode) all the time,
28
+ * and from updatedAt otherwise.
29
+ */
30
+ export default class SubscriberNotificationClaim {
31
+ /*
32
+ * Claim a Pending notification for this run. True when this run is now the
33
+ * one sending it; false when it is no longer Pending, or changed since the
34
+ * job read it (another run has it, or will read it afresh).
35
+ *
36
+ * `version` is the row's version as the job read it. A row read without
37
+ * one is claimed on its status alone.
38
+ *
39
+ * `claimedAtColumn` is stamped with the time of the claim, for the
40
+ * sweeper (see Incident.subscriberNotificationClaimedAtOnIncidentCreated).
41
+ *
42
+ * `alsoSet` settles other columns of the row in the same write, only if
43
+ * they still hold `expected`: the public note jobs use it to skip a note's
44
+ * update notification that the 'posted' notification they are claiming
45
+ * already covers (see the note jobs).
46
+ */
47
+ static async claim(data) {
48
+ var _a, _b;
49
+ return await data.service.compareAndSetColumnsByIdWithoutHooks({
50
+ id: data.id,
51
+ data: Object.assign(Object.assign(Object.assign({}, (((_a = data.alsoSet) === null || _a === void 0 ? void 0 : _a.data) || {})), { [data.statusColumn]: StatusPageSubscriberNotificationStatus.InProgress }), (data.claimedAtColumn
52
+ ? { [data.claimedAtColumn]: OneUptimeDate.getCurrentDate() }
53
+ : {})),
54
+ expectedData: Object.assign(Object.assign(Object.assign({}, (((_b = data.alsoSet) === null || _b === void 0 ? void 0 : _b.expected) || {})), { [data.statusColumn]: StatusPageSubscriberNotificationStatus.Pending }), (typeof data.version === "number" ? { version: data.version } : {})),
55
+ });
56
+ }
57
+ /*
58
+ * Fail a notification whose send was interrupted, with the reason, if it
59
+ * is still InProgress at the version the sweeper read. False when its send
60
+ * settled, or it was sent again, in the meantime.
61
+ */
62
+ static async failInterrupted(data) {
63
+ return await data.service.compareAndSetColumnsByIdWithoutHooks({
64
+ id: data.id,
65
+ data: {
66
+ [data.statusColumn]: StatusPageSubscriberNotificationStatus.Failed,
67
+ [data.messageColumn]: data.message,
68
+ },
69
+ expectedData: Object.assign({ [data.statusColumn]: StatusPageSubscriberNotificationStatus.InProgress }, (typeof data.version === "number" ? { version: data.version } : {})),
70
+ });
71
+ }
72
+ }
73
+ //# sourceMappingURL=SubscriberNotificationClaim.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SubscriberNotificationClaim.js","sourceRoot":"","sources":["../../../../../Server/Utils/StatusPage/SubscriberNotificationClaim.ts"],"names":[],"mappings":"AAEA,OAAO,aAAa,MAAM,qBAAqB,CAAC;AAEhD,OAAO,sCAAsC,MAAM,kEAAkE,CAAC;AAGtH;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,MAAM,CAAC,OAAO,OAAO,2BAA2B;IAC9C;;;;;;;;;;;;;;;OAeG;IACI,MAAM,CAAC,KAAK,CAAC,KAAK,CAA+B,IAYvD;;QACC,OAAO,MAAM,IAAI,CAAC,OAAO,CAAC,oCAAoC,CAAC;YAC7D,EAAE,EAAE,IAAI,CAAC,EAAE;YACX,IAAI,EAAE,8CACD,CAAC,CAAA,MAAA,IAAI,CAAC,OAAO,0CAAE,IAAI,KAAI,EAAE,CAAC,KAC7B,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,sCAAsC,CAAC,UAAU,KACnE,CAAC,IAAI,CAAC,eAAe;gBACtB,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,eAAe,CAAC,EAAE,aAAa,CAAC,cAAc,EAAE,EAAE;gBAC5D,CAAC,CAAC,EAAE,CAAC,CACgC;YACzC,YAAY,EAAE,8CACT,CAAC,CAAA,MAAA,IAAI,CAAC,OAAO,0CAAE,QAAQ,KAAI,EAAE,CAAC,KACjC,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,sCAAsC,CAAC,OAAO,KAChE,CAAC,OAAO,IAAI,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAC/B;SAC1C,CAAC,CAAC;IACL,CAAC;IAED;;;;OAIG;IACI,MAAM,CAAC,KAAK,CAAC,eAAe,CAA+B,IAOjE;QACC,OAAO,MAAM,IAAI,CAAC,OAAO,CAAC,oCAAoC,CAAC;YAC7D,EAAE,EAAE,IAAI,CAAC,EAAE;YACX,IAAI,EAAE;gBACJ,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,sCAAsC,CAAC,MAAM;gBAClE,CAAC,IAAI,CAAC,aAAa,CAAC,EAAE,IAAI,CAAC,OAAO;aACK;YACzC,YAAY,EAAE,gBACZ,CAAC,IAAI,CAAC,YAAY,CAAC,EAAE,sCAAsC,CAAC,UAAU,IACnE,CAAC,OAAO,IAAI,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAC/B;SAC1C,CAAC,CAAC;IACL,CAAC;CACF"}