@oneuptime/common 12.0.18 → 12.0.19

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 (206) hide show
  1. package/Models/DatabaseModels/EnterpriseLicense.ts +23 -0
  2. package/Models/DatabaseModels/Index.ts +4 -2
  3. package/Models/DatabaseModels/Monitor.ts +39 -9
  4. package/Models/DatabaseModels/UserMicrosoftTeams.ts +344 -0
  5. package/Models/DatabaseModels/UserNotificationRule.ts +144 -8
  6. package/Models/DatabaseModels/UserNotificationSetting.ts +34 -0
  7. package/Models/DatabaseModels/UserOnCallLogTimeline.ts +95 -0
  8. package/Models/DatabaseModels/UserSlack.ts +341 -0
  9. package/Models/DatabaseModels/WorkspaceProjectAuthToken.ts +9 -0
  10. package/Server/API/UserMicrosoftTeamsAPI.ts +127 -0
  11. package/Server/API/UserSlackAPI.ts +125 -0
  12. package/Server/EnvironmentConfig.ts +12 -107
  13. package/Server/Infrastructure/Postgres/SchemaMigrations/1788700000000-RemoveMarketingConversionUploadState.ts +33 -0
  14. package/Server/Infrastructure/Postgres/SchemaMigrations/1788800000000-DropMarketingConversionAddEnterpriseLicenseEmail.ts +51 -0
  15. package/Server/Infrastructure/Postgres/SchemaMigrations/1788900000000-RedactStoredMonitorIngestSecrets.ts +117 -0
  16. package/Server/Infrastructure/Postgres/SchemaMigrations/1789000000000-AddUserSlackAndMicrosoftTeams.ts +197 -0
  17. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +8 -0
  18. package/Server/Infrastructure/Queue.ts +7 -0
  19. package/Server/Services/EnterpriseLicenseService.ts +60 -0
  20. package/Server/Services/Index.ts +6 -2
  21. package/Server/Services/LlmLogService.ts +25 -9
  22. package/Server/Services/OnCallReadinessService.ts +86 -2
  23. package/Server/Services/ProjectService.ts +67 -0
  24. package/Server/Services/UserMicrosoftTeamsService.ts +208 -0
  25. package/Server/Services/UserNotificationMethodAdminService.ts +167 -5
  26. package/Server/Services/UserNotificationRuleAdminService.ts +40 -6
  27. package/Server/Services/UserNotificationRuleService.ts +589 -11
  28. package/Server/Services/UserNotificationSettingService.ts +138 -0
  29. package/Server/Services/UserService.ts +28 -0
  30. package/Server/Services/UserSlackService.ts +218 -0
  31. package/Server/Services/WorkspaceProjectAuthTokenService.ts +67 -1
  32. package/Server/Services/WorkspaceUserAuthTokenService.ts +73 -0
  33. package/Server/Services/WorkspaceUserNotificationService.ts +190 -0
  34. package/Server/Utils/Marketing/MarketingEventUtil.ts +145 -0
  35. package/Server/Utils/Marketing/MarketingEventWebhook.ts +114 -0
  36. package/Server/Utils/Monitor/MonitorLogUtil.ts +14 -1
  37. package/Server/Utils/Monitor/MonitorPayloadRedaction.ts +321 -0
  38. package/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.ts +191 -4
  39. package/Tests/App/Dashboard/AdminNotificationRulesPage.test.tsx +22 -14
  40. package/Tests/App/Dashboard/AdminUserNotificationMethodsPage.test.tsx +22 -11
  41. package/Tests/App/Dashboard/OnCallPreventionGuards.test.tsx +37 -1
  42. package/Tests/App/Dashboard/OnCallRulesTable.test.tsx +18 -10
  43. package/Tests/Models/DatabaseModels/DomainRoleTierCoverage.test.ts +27 -1
  44. package/Tests/Models/DatabaseModels/MonitorSecretKeyColumnAccessControl.test.ts +214 -0
  45. package/Tests/Server/API/OnCallReadinessAPI.test.ts +145 -26
  46. package/Tests/Server/API/UserNotificationMethodAdminAPI.test.ts +2 -2
  47. package/Tests/Server/Services/AIServiceDailyBudget.test.ts +11 -1
  48. package/Tests/Server/Services/AdminRuleEditGuards.test.ts +22 -8
  49. package/Tests/Server/Services/DeliverNotificationForRuleExtraction.test.ts +18 -2
  50. package/Tests/Server/Services/EpisodeRuleSeverityRepair.test.ts +5 -1
  51. package/Tests/Server/Services/LlmLogServiceTokenAggregateParams.test.ts +640 -0
  52. package/Tests/Server/Services/NotificationChannelEventCoverage.test.ts +246 -22
  53. package/Tests/Server/Services/NotificationDeletionImpact.test.ts +136 -8
  54. package/Tests/Server/Services/OnCallNotificationFallback.test.ts +191 -8
  55. package/Tests/Server/Services/OnCallReadinessService.test.ts +343 -18
  56. package/Tests/Server/Services/SeverityRuleBackfill.test.ts +5 -1
  57. package/Tests/Server/Services/UserMicrosoftTeamsService.test.ts +343 -0
  58. package/Tests/Server/Services/UserNotificationMethodAdminService.test.ts +209 -8
  59. package/Tests/Server/Services/UserNotificationRuleAdminGuards.test.ts +22 -6
  60. package/Tests/Server/Services/UserNotificationRuleDefaultCreation.test.ts +12 -6
  61. package/Tests/Server/Services/UserNotificationRuleExecuteItem.test.ts +37 -3
  62. package/Tests/Server/Services/UserNotificationRuleWorkspaceDelivery.test.ts +669 -0
  63. package/Tests/Server/Services/UserNotificationSettingWorkspaceChannels.test.ts +410 -0
  64. package/Tests/Server/Services/UserSlackService.test.ts +407 -0
  65. package/Tests/Server/Services/WorkspaceProjectAuthTokenDisconnectCascade.test.ts +224 -0
  66. package/Tests/Server/Services/WorkspaceUserAuthTokenNotificationMethodCascade.test.ts +189 -0
  67. package/Tests/Server/Services/WorkspaceUserNotificationService.test.ts +496 -0
  68. package/Tests/Server/Types/Database/Permissions/AdminNotificationRuleAccess.test.ts +30 -17
  69. package/Tests/Server/Types/Database/Permissions/CreateOwnershipScoping.test.ts +8 -3
  70. package/Tests/Server/Types/Database/Permissions/OwnerOnlyColumns.test.ts +72 -3
  71. package/Tests/Server/Types/Database/Permissions/UserNotificationRuleScoping.test.ts +22 -18
  72. package/Tests/Server/Types/Database/Permissions/WorkspaceMethodStampedColumnCreate.test.ts +178 -0
  73. package/Tests/Server/Utils/Marketing/MarketingEventUtil.test.ts +259 -0
  74. package/Tests/Server/Utils/Marketing/MarketingEventWebhook.test.ts +257 -0
  75. package/Tests/Server/Utils/Monitor/MonitorLogUtilRedaction.test.ts +300 -0
  76. package/Tests/Server/Utils/Monitor/MonitorPayloadRedaction.test.ts +381 -0
  77. package/Tests/Server/Utils/Runbook/RunbookExecutePermission.test.ts +228 -0
  78. package/Tests/Server/Utils/SessionReplay/SessionReplayErasureTombstone.test.ts +189 -0
  79. package/Tests/Server/Utils/SessionReplay/SessionReplayUsage.test.ts +205 -0
  80. package/Tests/Server/Utils/Telemetry/AppMetrics.test.ts +275 -0
  81. package/Tests/Server/Utils/Telemetry/TelemetryContext.test.ts +279 -0
  82. package/Tests/Server/Utils/Workspace/MicrosoftTeamsDirectMessage.test.ts +454 -0
  83. package/Tests/UI/Utils/NotificationMethodUtil.test.ts +137 -9
  84. package/Tests/UI/Utils/PermissionGate.test.ts +105 -0
  85. package/Types/Marketing/MarketingEvent.ts +97 -0
  86. package/UI/Utils/NotificationMethodUtil.ts +41 -1
  87. package/UI/Utils/PermissionGate.ts +56 -0
  88. package/build/dist/Models/DatabaseModels/EnterpriseLicense.js +24 -0
  89. package/build/dist/Models/DatabaseModels/EnterpriseLicense.js.map +1 -1
  90. package/build/dist/Models/DatabaseModels/Index.js +4 -2
  91. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  92. package/build/dist/Models/DatabaseModels/Monitor.js +39 -9
  93. package/build/dist/Models/DatabaseModels/Monitor.js.map +1 -1
  94. package/build/dist/Models/DatabaseModels/UserMicrosoftTeams.js +363 -0
  95. package/build/dist/Models/DatabaseModels/UserMicrosoftTeams.js.map +1 -0
  96. package/build/dist/Models/DatabaseModels/UserNotificationRule.js +145 -8
  97. package/build/dist/Models/DatabaseModels/UserNotificationRule.js.map +1 -1
  98. package/build/dist/Models/DatabaseModels/UserNotificationSetting.js +38 -0
  99. package/build/dist/Models/DatabaseModels/UserNotificationSetting.js.map +1 -1
  100. package/build/dist/Models/DatabaseModels/UserOnCallLogTimeline.js +96 -0
  101. package/build/dist/Models/DatabaseModels/UserOnCallLogTimeline.js.map +1 -1
  102. package/build/dist/Models/DatabaseModels/UserSlack.js +361 -0
  103. package/build/dist/Models/DatabaseModels/UserSlack.js.map +1 -0
  104. package/build/dist/Models/DatabaseModels/WorkspaceProjectAuthToken.js.map +1 -1
  105. package/build/dist/Server/API/UserMicrosoftTeamsAPI.js +82 -0
  106. package/build/dist/Server/API/UserMicrosoftTeamsAPI.js.map +1 -0
  107. package/build/dist/Server/API/UserSlackAPI.js +81 -0
  108. package/build/dist/Server/API/UserSlackAPI.js.map +1 -0
  109. package/build/dist/Server/EnvironmentConfig.js +10 -70
  110. package/build/dist/Server/EnvironmentConfig.js.map +1 -1
  111. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1788700000000-RemoveMarketingConversionUploadState.js +26 -0
  112. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1788700000000-RemoveMarketingConversionUploadState.js.map +1 -0
  113. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1788800000000-DropMarketingConversionAddEnterpriseLicenseEmail.js +37 -0
  114. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1788800000000-DropMarketingConversionAddEnterpriseLicenseEmail.js.map +1 -0
  115. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1788900000000-RedactStoredMonitorIngestSecrets.js +106 -0
  116. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1788900000000-RedactStoredMonitorIngestSecrets.js.map +1 -0
  117. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789000000000-AddUserSlackAndMicrosoftTeams.js +78 -0
  118. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1789000000000-AddUserSlackAndMicrosoftTeams.js.map +1 -0
  119. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +8 -0
  120. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  121. package/build/dist/Server/Infrastructure/Queue.js +7 -0
  122. package/build/dist/Server/Infrastructure/Queue.js.map +1 -1
  123. package/build/dist/Server/Services/EnterpriseLicenseService.js +65 -0
  124. package/build/dist/Server/Services/EnterpriseLicenseService.js.map +1 -1
  125. package/build/dist/Server/Services/Index.js +6 -2
  126. package/build/dist/Server/Services/Index.js.map +1 -1
  127. package/build/dist/Server/Services/LlmLogService.js +25 -9
  128. package/build/dist/Server/Services/LlmLogService.js.map +1 -1
  129. package/build/dist/Server/Services/OnCallReadinessService.js +74 -2
  130. package/build/dist/Server/Services/OnCallReadinessService.js.map +1 -1
  131. package/build/dist/Server/Services/ProjectService.js +56 -0
  132. package/build/dist/Server/Services/ProjectService.js.map +1 -1
  133. package/build/dist/Server/Services/UserMicrosoftTeamsService.js +183 -0
  134. package/build/dist/Server/Services/UserMicrosoftTeamsService.js.map +1 -0
  135. package/build/dist/Server/Services/UserNotificationMethodAdminService.js +138 -2
  136. package/build/dist/Server/Services/UserNotificationMethodAdminService.js.map +1 -1
  137. package/build/dist/Server/Services/UserNotificationRuleAdminService.js +32 -4
  138. package/build/dist/Server/Services/UserNotificationRuleAdminService.js.map +1 -1
  139. package/build/dist/Server/Services/UserNotificationRuleService.js +499 -67
  140. package/build/dist/Server/Services/UserNotificationRuleService.js.map +1 -1
  141. package/build/dist/Server/Services/UserNotificationSettingService.js +118 -0
  142. package/build/dist/Server/Services/UserNotificationSettingService.js.map +1 -1
  143. package/build/dist/Server/Services/UserService.js +26 -1
  144. package/build/dist/Server/Services/UserService.js.map +1 -1
  145. package/build/dist/Server/Services/UserSlackService.js +195 -0
  146. package/build/dist/Server/Services/UserSlackService.js.map +1 -0
  147. package/build/dist/Server/Services/WorkspaceProjectAuthTokenService.js +64 -1
  148. package/build/dist/Server/Services/WorkspaceProjectAuthTokenService.js.map +1 -1
  149. package/build/dist/Server/Services/WorkspaceUserAuthTokenService.js +70 -0
  150. package/build/dist/Server/Services/WorkspaceUserAuthTokenService.js.map +1 -1
  151. package/build/dist/Server/Services/WorkspaceUserNotificationService.js +129 -0
  152. package/build/dist/Server/Services/WorkspaceUserNotificationService.js.map +1 -0
  153. package/build/dist/Server/Utils/Marketing/MarketingEventUtil.js +94 -0
  154. package/build/dist/Server/Utils/Marketing/MarketingEventUtil.js.map +1 -0
  155. package/build/dist/Server/Utils/Marketing/MarketingEventWebhook.js +93 -0
  156. package/build/dist/Server/Utils/Marketing/MarketingEventWebhook.js.map +1 -0
  157. package/build/dist/Server/Utils/Monitor/MonitorLogUtil.js +12 -1
  158. package/build/dist/Server/Utils/Monitor/MonitorLogUtil.js.map +1 -1
  159. package/build/dist/Server/Utils/Monitor/MonitorPayloadRedaction.js +233 -0
  160. package/build/dist/Server/Utils/Monitor/MonitorPayloadRedaction.js.map +1 -0
  161. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js +141 -4
  162. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/MicrosoftTeams.js.map +1 -1
  163. package/build/dist/Types/Marketing/MarketingEvent.js +43 -0
  164. package/build/dist/Types/Marketing/MarketingEvent.js.map +1 -0
  165. package/build/dist/UI/Utils/NotificationMethodUtil.js +33 -1
  166. package/build/dist/UI/Utils/NotificationMethodUtil.js.map +1 -1
  167. package/build/dist/UI/Utils/PermissionGate.js +32 -0
  168. package/build/dist/UI/Utils/PermissionGate.js.map +1 -1
  169. package/package.json +1 -1
  170. package/Models/DatabaseModels/MarketingConversion.ts +0 -410
  171. package/Server/Services/MarketingConversionService.ts +0 -10
  172. package/Server/Utils/Marketing/ConversionUploadProvider.ts +0 -215
  173. package/Server/Utils/Marketing/ConversionUploadProviders.ts +0 -22
  174. package/Server/Utils/Marketing/Providers/GoogleAds.ts +0 -333
  175. package/Server/Utils/Marketing/Providers/LinkedIn.ts +0 -185
  176. package/Server/Utils/Marketing/Providers/Meta.ts +0 -182
  177. package/Server/Utils/Marketing/Providers/MicrosoftAds.ts +0 -223
  178. package/Server/Utils/Marketing/Providers/Reddit.ts +0 -208
  179. package/Tests/Server/Utils/Marketing/AdUploadableConversionTypes.test.ts +0 -315
  180. package/Tests/Server/Utils/Marketing/ConversionUploadProvider.test.ts +0 -300
  181. package/Tests/Server/Utils/Marketing/GoogleAds.test.ts +0 -592
  182. package/Tests/Server/Utils/Marketing/LinkedIn.test.ts +0 -282
  183. package/Tests/Server/Utils/Marketing/Meta.test.ts +0 -304
  184. package/Tests/Server/Utils/Marketing/MicrosoftAds.test.ts +0 -263
  185. package/Tests/Server/Utils/Marketing/Reddit.test.ts +0 -259
  186. package/Types/Marketing/MarketingConversion.ts +0 -53
  187. package/build/dist/Models/DatabaseModels/MarketingConversion.js +0 -445
  188. package/build/dist/Models/DatabaseModels/MarketingConversion.js.map +0 -1
  189. package/build/dist/Server/Services/MarketingConversionService.js +0 -9
  190. package/build/dist/Server/Services/MarketingConversionService.js.map +0 -1
  191. package/build/dist/Server/Utils/Marketing/ConversionUploadProvider.js +0 -93
  192. package/build/dist/Server/Utils/Marketing/ConversionUploadProvider.js.map +0 -1
  193. package/build/dist/Server/Utils/Marketing/ConversionUploadProviders.js +0 -20
  194. package/build/dist/Server/Utils/Marketing/ConversionUploadProviders.js.map +0 -1
  195. package/build/dist/Server/Utils/Marketing/Providers/GoogleAds.js +0 -221
  196. package/build/dist/Server/Utils/Marketing/Providers/GoogleAds.js.map +0 -1
  197. package/build/dist/Server/Utils/Marketing/Providers/LinkedIn.js +0 -137
  198. package/build/dist/Server/Utils/Marketing/Providers/LinkedIn.js.map +0 -1
  199. package/build/dist/Server/Utils/Marketing/Providers/Meta.js +0 -133
  200. package/build/dist/Server/Utils/Marketing/Providers/Meta.js.map +0 -1
  201. package/build/dist/Server/Utils/Marketing/Providers/MicrosoftAds.js +0 -143
  202. package/build/dist/Server/Utils/Marketing/Providers/MicrosoftAds.js.map +0 -1
  203. package/build/dist/Server/Utils/Marketing/Providers/Reddit.js +0 -145
  204. package/build/dist/Server/Utils/Marketing/Providers/Reddit.js.map +0 -1
  205. package/build/dist/Types/Marketing/MarketingConversion.js +0 -52
  206. package/build/dist/Types/Marketing/MarketingConversion.js.map +0 -1
@@ -23,8 +23,11 @@ import UserCallService from "./UserCallService";
23
23
  import UserPushService from "./UserPushService";
24
24
  import UserSmsService from "./UserSmsService";
25
25
  import UserTelegramService from "./UserTelegramService";
26
+ import UserSlackService from "./UserSlackService";
27
+ import UserMicrosoftTeamsService from "./UserMicrosoftTeamsService";
26
28
  import UserWebhookService from "./UserWebhookService";
27
29
  import UserWhatsAppService from "./UserWhatsAppService";
30
+ import WorkspaceUserNotificationService from "./WorkspaceUserNotificationService";
28
31
  import ProjectService from "./ProjectService";
29
32
  import UserNotificationRuleAdminService, {
30
33
  RuleColumnCarrier,
@@ -84,6 +87,8 @@ import UserEmail from "../../Models/DatabaseModels/UserEmail";
84
87
  import UserPush from "../../Models/DatabaseModels/UserPush";
85
88
  import UserSMS from "../../Models/DatabaseModels/UserSMS";
86
89
  import UserTelegram from "../../Models/DatabaseModels/UserTelegram";
90
+ import UserSlack from "../../Models/DatabaseModels/UserSlack";
91
+ import UserMicrosoftTeams from "../../Models/DatabaseModels/UserMicrosoftTeams";
87
92
  import UserWebhook from "../../Models/DatabaseModels/UserWebhook";
88
93
  import UserWhatsApp from "../../Models/DatabaseModels/UserWhatsApp";
89
94
  import Model from "../../Models/DatabaseModels/UserNotificationRule";
@@ -106,6 +111,13 @@ import WorkspaceNotificationRuleService from "./WorkspaceNotificationRuleService
106
111
  import PushNotificationService from "./PushNotificationService";
107
112
  import NotificationRuleEventType from "../../Types/Workspace/NotificationRules/EventType";
108
113
  import NotificationRuleWorkspaceChannel from "../../Types/Workspace/NotificationRules/NotificationRuleWorkspaceChannel";
114
+ import WorkspaceType, {
115
+ getWorkspaceTypeDisplayName,
116
+ } from "../../Types/Workspace/WorkspaceType";
117
+ import {
118
+ WorkspaceMessageBlock,
119
+ WorkspacePayloadMarkdown,
120
+ } from "../../Types/Workspace/WorkspaceMessagePayload";
109
121
  import PushNotificationUtil from "../Utils/PushNotificationUtil";
110
122
  import PushNotificationMessage from "../../Types/PushNotification/PushNotificationMessage";
111
123
  import logger, { LogAttributes } from "../Utils/Logger";
@@ -117,6 +129,8 @@ export interface NotificationMethodDescriptor {
117
129
  userCallId?: ObjectID;
118
130
  userWhatsAppId?: ObjectID;
119
131
  userTelegramId?: ObjectID;
132
+ userSlackId?: ObjectID;
133
+ userMicrosoftTeamsId?: ObjectID;
120
134
  userPushId?: ObjectID;
121
135
  userWebhookId?: ObjectID;
122
136
  }
@@ -504,12 +518,13 @@ const HANDOFF_RULE_TYPES: Array<NotificationRuleType> = [
504
518
  type ChannelListFunction = () => Array<string>;
505
519
 
506
520
  /**
507
- * The three channels no project setting can switch off. Push and Email are
508
- * zero-cost and Webhook is somebody else's endpoint, so nothing gates them
509
- * which is what makes "a verified one of these survives" a CERTAIN answer to
510
- * "can this person still be paged" rather than a hopeful one. Kept in step with
511
- * OnCallReadinessService.isChannelEnabled, which returns true for exactly these
512
- * three unconditionally.
521
+ * The channels no project setting can switch off. Push and Email are
522
+ * zero-cost, Webhook is somebody else's endpoint, and Slack / Microsoft Teams
523
+ * ride on the project's own workspace connection at no per-message cost, so
524
+ * nothing gates them which is what makes "a verified one of these survives"
525
+ * a CERTAIN answer to "can this person still be paged" rather than a hopeful
526
+ * one. Kept in step with OnCallReadinessService.isChannelEnabled, which
527
+ * returns true for exactly these five unconditionally.
513
528
  *
514
529
  * A FUNCTION rather than a module-level constant, and that is load-bearing
515
530
  * rather than stylistic: this module and OnCallReadinessService import each
@@ -525,6 +540,8 @@ const channelsWithNoProjectSwitch: ChannelListFunction = (): Array<string> => {
525
540
  return [
526
541
  ReadinessMethodType.Push,
527
542
  ReadinessMethodType.Email,
543
+ ReadinessMethodType.Slack,
544
+ ReadinessMethodType.MicrosoftTeams,
528
545
  ReadinessMethodType.Webhook,
529
546
  ];
530
547
  };
@@ -628,6 +645,18 @@ export class Service extends DatabaseService<Model> {
628
645
  isVerified: true,
629
646
  userId: true,
630
647
  },
648
+ userSlack: {
649
+ slackUserId: true,
650
+ slackUserName: true,
651
+ isVerified: true,
652
+ userId: true,
653
+ },
654
+ userMicrosoftTeams: {
655
+ microsoftTeamsUserId: true,
656
+ microsoftTeamsUserName: true,
657
+ isVerified: true,
658
+ userId: true,
659
+ },
631
660
  userWebhook: {
632
661
  webhookUrl: true,
633
662
  name: true,
@@ -732,6 +761,14 @@ export class Service extends DatabaseService<Model> {
732
761
  label: "Telegram",
733
762
  ownerUserId: notificationRuleItem.userTelegram?.userId,
734
763
  },
764
+ {
765
+ label: "Slack",
766
+ ownerUserId: notificationRuleItem.userSlack?.userId,
767
+ },
768
+ {
769
+ label: "Microsoft Teams",
770
+ ownerUserId: notificationRuleItem.userMicrosoftTeams?.userId,
771
+ },
735
772
  { label: "Push", ownerUserId: notificationRuleItem.userPush?.userId },
736
773
  {
737
774
  label: "Webhook",
@@ -1987,6 +2024,84 @@ export class Service extends DatabaseService<Model> {
1987
2024
  });
1988
2025
  }
1989
2026
 
2027
+ // send Slack.
2028
+ if (
2029
+ notificationRuleItem.userSlack?.slackUserId &&
2030
+ notificationRuleItem.userSlack?.isVerified
2031
+ ) {
2032
+ const attempted: boolean =
2033
+ await this.deliverWorkspaceDirectMessageForRule({
2034
+ workspaceType: WorkspaceType.Slack,
2035
+ methodId: notificationRuleItem.userSlack.id!,
2036
+ workspaceUserId: notificationRuleItem.userSlack.slackUserId,
2037
+ notificationRuleItem: notificationRuleItem,
2038
+ options: options,
2039
+ logTimelineItem: logTimelineItem,
2040
+ incident: incident,
2041
+ alert: alert,
2042
+ alertEpisode: alertEpisode,
2043
+ incidentEpisode: incidentEpisode,
2044
+ });
2045
+
2046
+ deliveryAttempted = deliveryAttempted || attempted;
2047
+ }
2048
+
2049
+ if (
2050
+ notificationRuleItem.userSlack &&
2051
+ !notificationRuleItem.userSlack?.isVerified
2052
+ ) {
2053
+ logTimelineItem.status = UserNotificationStatus.Error;
2054
+ logTimelineItem.statusMessage = `Slack message not sent because the Slack account is not verified.`;
2055
+ logTimelineItem.userSlackId = notificationRuleItem.userSlack.id!;
2056
+
2057
+ await UserOnCallLogTimelineService.create({
2058
+ data: logTimelineItem,
2059
+ props: {
2060
+ isRoot: true,
2061
+ },
2062
+ });
2063
+ }
2064
+
2065
+ // send Microsoft Teams.
2066
+ if (
2067
+ notificationRuleItem.userMicrosoftTeams?.microsoftTeamsUserId &&
2068
+ notificationRuleItem.userMicrosoftTeams?.isVerified
2069
+ ) {
2070
+ const attempted: boolean =
2071
+ await this.deliverWorkspaceDirectMessageForRule({
2072
+ workspaceType: WorkspaceType.MicrosoftTeams,
2073
+ methodId: notificationRuleItem.userMicrosoftTeams.id!,
2074
+ workspaceUserId:
2075
+ notificationRuleItem.userMicrosoftTeams.microsoftTeamsUserId,
2076
+ notificationRuleItem: notificationRuleItem,
2077
+ options: options,
2078
+ logTimelineItem: logTimelineItem,
2079
+ incident: incident,
2080
+ alert: alert,
2081
+ alertEpisode: alertEpisode,
2082
+ incidentEpisode: incidentEpisode,
2083
+ });
2084
+
2085
+ deliveryAttempted = deliveryAttempted || attempted;
2086
+ }
2087
+
2088
+ if (
2089
+ notificationRuleItem.userMicrosoftTeams &&
2090
+ !notificationRuleItem.userMicrosoftTeams?.isVerified
2091
+ ) {
2092
+ logTimelineItem.status = UserNotificationStatus.Error;
2093
+ logTimelineItem.statusMessage = `Microsoft Teams message not sent because the Microsoft Teams account is not verified.`;
2094
+ logTimelineItem.userMicrosoftTeamsId =
2095
+ notificationRuleItem.userMicrosoftTeams.id!;
2096
+
2097
+ await UserOnCallLogTimelineService.create({
2098
+ data: logTimelineItem,
2099
+ props: {
2100
+ isRoot: true,
2101
+ },
2102
+ });
2103
+ }
2104
+
1990
2105
  // send webhook.
1991
2106
  if (notificationRuleItem.userWebhook?.webhookUrl) {
1992
2107
  const webhookUrl: string = notificationRuleItem.userWebhook.webhookUrl;
@@ -2819,6 +2934,191 @@ export class Service extends DatabaseService<Model> {
2819
2934
  return deliveryAttempted;
2820
2935
  }
2821
2936
 
2937
+ /*
2938
+ * The Slack and Microsoft Teams halves of deliverNotificationForRule. Both
2939
+ * channels deliver the same way — the same generated message blocks handed
2940
+ * to the same direct-message sender, with only the workspace type and the
2941
+ * timeline method column differing — so one helper carries both instead of
2942
+ * two more copies of the per-event ladder above.
2943
+ *
2944
+ * Returns whether a delivery was attempted. `false` means this event type
2945
+ * has no workspace template, and the caller's fell-through guard turns that
2946
+ * into a loud Error row rather than a silent nothing.
2947
+ */
2948
+ private async deliverWorkspaceDirectMessageForRule(data: {
2949
+ workspaceType: WorkspaceType;
2950
+ methodId: ObjectID;
2951
+ workspaceUserId: string;
2952
+ notificationRuleItem: Model;
2953
+ options: ExecuteNotificationRuleOptions;
2954
+ logTimelineItem: UserOnCallLogTimeline;
2955
+ incident: Incident | null;
2956
+ alert: Alert | null;
2957
+ alertEpisode: AlertEpisode | null;
2958
+ incidentEpisode: IncidentEpisode | null;
2959
+ }): Promise<boolean> {
2960
+ const channelDisplayName: string = getWorkspaceTypeDisplayName(
2961
+ data.workspaceType,
2962
+ );
2963
+ const options: ExecuteNotificationRuleOptions = data.options;
2964
+
2965
+ /*
2966
+ * Resolve the event into the entity being paged about, the block
2967
+ * generator for it, and the ids the send should be correlated with. The
2968
+ * generator is deferred because the message embeds the timeline row id,
2969
+ * which does not exist until the row below is created.
2970
+ */
2971
+ let entityProjectId: ObjectID | undefined = undefined;
2972
+ let incidentId: ObjectID | undefined = undefined;
2973
+ let alertId: ObjectID | undefined = undefined;
2974
+ let alertEpisodeId: ObjectID | undefined = undefined;
2975
+ let incidentEpisodeId: ObjectID | undefined = undefined;
2976
+ let generateBlocks:
2977
+ | ((timelineId: ObjectID) => Promise<Array<WorkspaceMessageBlock>>)
2978
+ | null = null;
2979
+ let messageSummary: string = "";
2980
+
2981
+ if (
2982
+ options.userNotificationEventType ===
2983
+ UserNotificationEventType.IncidentCreated &&
2984
+ data.incident
2985
+ ) {
2986
+ const incident: Incident = data.incident;
2987
+ entityProjectId = incident.projectId;
2988
+ incidentId = incident.id!;
2989
+ messageSummary = `On-call notification: incident created.`;
2990
+ generateBlocks = (
2991
+ timelineId: ObjectID,
2992
+ ): Promise<Array<WorkspaceMessageBlock>> => {
2993
+ return this.generateWorkspaceMessageBlocksForIncidentCreated(
2994
+ incident,
2995
+ timelineId,
2996
+ );
2997
+ };
2998
+ }
2999
+
3000
+ if (
3001
+ options.userNotificationEventType ===
3002
+ UserNotificationEventType.AlertCreated &&
3003
+ data.alert
3004
+ ) {
3005
+ const alert: Alert = data.alert;
3006
+ entityProjectId = alert.projectId;
3007
+ alertId = alert.id!;
3008
+ messageSummary = `On-call notification: alert created.`;
3009
+ generateBlocks = (
3010
+ timelineId: ObjectID,
3011
+ ): Promise<Array<WorkspaceMessageBlock>> => {
3012
+ return this.generateWorkspaceMessageBlocksForAlertCreated(
3013
+ alert,
3014
+ timelineId,
3015
+ );
3016
+ };
3017
+ }
3018
+
3019
+ if (
3020
+ options.userNotificationEventType ===
3021
+ UserNotificationEventType.AlertEpisodeCreated &&
3022
+ data.alertEpisode
3023
+ ) {
3024
+ const alertEpisode: AlertEpisode = data.alertEpisode;
3025
+ entityProjectId = alertEpisode.projectId;
3026
+ alertEpisodeId = alertEpisode.id!;
3027
+ messageSummary = `On-call notification: alert episode created.`;
3028
+ generateBlocks = (
3029
+ timelineId: ObjectID,
3030
+ ): Promise<Array<WorkspaceMessageBlock>> => {
3031
+ return this.generateWorkspaceMessageBlocksForAlertEpisodeCreated(
3032
+ alertEpisode,
3033
+ timelineId,
3034
+ );
3035
+ };
3036
+ }
3037
+
3038
+ if (
3039
+ options.userNotificationEventType ===
3040
+ UserNotificationEventType.IncidentEpisodeCreated &&
3041
+ data.incidentEpisode
3042
+ ) {
3043
+ const incidentEpisode: IncidentEpisode = data.incidentEpisode;
3044
+ entityProjectId = incidentEpisode.projectId;
3045
+ incidentEpisodeId = incidentEpisode.id!;
3046
+ messageSummary = `On-call notification: incident episode created.`;
3047
+ generateBlocks = (
3048
+ timelineId: ObjectID,
3049
+ ): Promise<Array<WorkspaceMessageBlock>> => {
3050
+ return this.generateWorkspaceMessageBlocksForIncidentEpisodeCreated(
3051
+ incidentEpisode,
3052
+ timelineId,
3053
+ );
3054
+ };
3055
+ }
3056
+
3057
+ if (!generateBlocks) {
3058
+ return false;
3059
+ }
3060
+
3061
+ data.logTimelineItem.status = UserNotificationStatus.Sending;
3062
+ data.logTimelineItem.statusMessage = `Sending ${channelDisplayName} message.`;
3063
+
3064
+ if (data.workspaceType === WorkspaceType.Slack) {
3065
+ data.logTimelineItem.userSlackId = data.methodId;
3066
+ }
3067
+
3068
+ if (data.workspaceType === WorkspaceType.MicrosoftTeams) {
3069
+ data.logTimelineItem.userMicrosoftTeamsId = data.methodId;
3070
+ }
3071
+
3072
+ const updatedLog: UserOnCallLogTimeline =
3073
+ await UserOnCallLogTimelineService.create({
3074
+ data: data.logTimelineItem,
3075
+ props: {
3076
+ isRoot: true,
3077
+ },
3078
+ });
3079
+
3080
+ const messageBlocks: Array<WorkspaceMessageBlock> = await generateBlocks(
3081
+ updatedLog.id!,
3082
+ );
3083
+
3084
+ /*
3085
+ * Fire-and-forget like every other channel: the sender flips the timeline
3086
+ * row to Sent / Error itself, and the .catch is the safety net for a
3087
+ * rejection raised before it gets that far.
3088
+ */
3089
+ WorkspaceUserNotificationService.sendDirectMessageToUser({
3090
+ projectId: entityProjectId || options.projectId,
3091
+ workspaceType: data.workspaceType,
3092
+ workspaceUserId: data.workspaceUserId,
3093
+ messageBlocks: messageBlocks,
3094
+ messageSummary: messageSummary,
3095
+ userId: data.notificationRuleItem.userId!,
3096
+ userOnCallLogTimelineId: updatedLog.id!,
3097
+ incidentId: incidentId,
3098
+ alertId: alertId,
3099
+ alertEpisodeId: alertEpisodeId,
3100
+ incidentEpisodeId: incidentEpisodeId,
3101
+ onCallPolicyId: options.onCallPolicyId,
3102
+ onCallPolicyEscalationRuleId: options.onCallPolicyEscalationRuleId,
3103
+ teamId: options.userBelongsToTeamId,
3104
+ onCallScheduleId: options.onCallScheduleId,
3105
+ }).catch(async (err: Error) => {
3106
+ await UserOnCallLogTimelineService.updateOneById({
3107
+ id: updatedLog.id!,
3108
+ data: {
3109
+ status: UserNotificationStatus.Error,
3110
+ statusMessage:
3111
+ err.message || `Error sending ${channelDisplayName} message.`,
3112
+ },
3113
+ props: {
3114
+ isRoot: true,
3115
+ },
3116
+ });
3117
+ });
3118
+
3119
+ return true;
3120
+ }
3121
+
2822
3122
  /*
2823
3123
  * The channels this rule could actually reach the user on, by display name.
2824
3124
  *
@@ -2861,6 +3161,20 @@ export class Service extends DatabaseService<Model> {
2861
3161
  channels.push("Telegram");
2862
3162
  }
2863
3163
 
3164
+ if (
3165
+ notificationRuleItem.userSlack?.slackUserId &&
3166
+ notificationRuleItem.userSlack?.isVerified
3167
+ ) {
3168
+ channels.push("Slack");
3169
+ }
3170
+
3171
+ if (
3172
+ notificationRuleItem.userMicrosoftTeams?.microsoftTeamsUserId &&
3173
+ notificationRuleItem.userMicrosoftTeams?.isVerified
3174
+ ) {
3175
+ channels.push("Microsoft Teams");
3176
+ }
3177
+
2864
3178
  if (notificationRuleItem.userWebhook?.webhookUrl) {
2865
3179
  channels.push("Webhook");
2866
3180
  }
@@ -3021,10 +3335,11 @@ export class Service extends DatabaseService<Model> {
3021
3335
  /*
3022
3336
  * Pick what to page the user on, and build an unsaved rule for each choice.
3023
3337
  *
3024
- * Zero-cost channels win: push and email reach the most people for no money
3025
- * and no billing surprise, and there is no reason to pick between them, so a
3026
- * user who has both gets both. Only a user with neither is worth spending on,
3027
- * and then just once, in escalating-intrusiveness order.
3338
+ * Zero-cost channels win: push, email, Slack and Microsoft Teams reach the
3339
+ * most people for no money and no billing surprise, and there is no reason
3340
+ * to pick between them, so a user who has several gets all of them. Only a
3341
+ * user with none of these is worth spending on, and then just once, in
3342
+ * escalating-intrusiveness order.
3028
3343
  *
3029
3344
  * Paid channels are additionally gated on the project's own enable flags.
3030
3345
  * SmsService and CallService enforce those at send time, but WhatsApp and
@@ -3083,6 +3398,55 @@ export class Service extends DatabaseService<Model> {
3083
3398
  chosen.push({ channelName: "Email", rule: rule });
3084
3399
  }
3085
3400
 
3401
+ const userSlack: UserSlack | null = await UserSlackService.findOneBy({
3402
+ query: {
3403
+ projectId: options.projectId,
3404
+ userId: options.userId,
3405
+ isVerified: true,
3406
+ },
3407
+ select: {
3408
+ _id: true,
3409
+ slackUserId: true,
3410
+ slackUserName: true,
3411
+ isVerified: true,
3412
+ },
3413
+ props: {
3414
+ isRoot: true,
3415
+ },
3416
+ });
3417
+
3418
+ if (userSlack) {
3419
+ const rule: Model = this.buildUnsavedFallbackRule(options);
3420
+ rule.userSlack = userSlack;
3421
+ rule.userSlackId = userSlack.id!;
3422
+ chosen.push({ channelName: "Slack", rule: rule });
3423
+ }
3424
+
3425
+ const userMicrosoftTeams: UserMicrosoftTeams | null =
3426
+ await UserMicrosoftTeamsService.findOneBy({
3427
+ query: {
3428
+ projectId: options.projectId,
3429
+ userId: options.userId,
3430
+ isVerified: true,
3431
+ },
3432
+ select: {
3433
+ _id: true,
3434
+ microsoftTeamsUserId: true,
3435
+ microsoftTeamsUserName: true,
3436
+ isVerified: true,
3437
+ },
3438
+ props: {
3439
+ isRoot: true,
3440
+ },
3441
+ });
3442
+
3443
+ if (userMicrosoftTeams) {
3444
+ const rule: Model = this.buildUnsavedFallbackRule(options);
3445
+ rule.userMicrosoftTeams = userMicrosoftTeams;
3446
+ rule.userMicrosoftTeamsId = userMicrosoftTeams.id!;
3447
+ chosen.push({ channelName: "Microsoft Teams", rule: rule });
3448
+ }
3449
+
3086
3450
  if (chosen.length > 0) {
3087
3451
  return chosen;
3088
3452
  }
@@ -3809,6 +4173,180 @@ export class Service extends DatabaseService<Model> {
3809
4173
  return lines.join("\n");
3810
4174
  }
3811
4175
 
4176
+ /*
4177
+ * ---------------------------------------------------------------------- *
4178
+ * Workspace (Slack / Microsoft Teams) direct-message generators.
4179
+ *
4180
+ * One generator family serves BOTH workspace channels: the blocks are
4181
+ * written in standard markdown, which SlackUtil slackifies and
4182
+ * MicrosoftTeamsUtil renders into an adaptive card. Keep them to the block
4183
+ * types both platforms implement (markdown / header / divider / buttons) —
4184
+ * anything else throws NotImplementedException on Teams.
4185
+ * ---------------------------------------------------------------------- *
4186
+ */
4187
+
4188
+ private buildWorkspaceMessageBlocks(data: {
4189
+ headline: string;
4190
+ identifier: string;
4191
+ dashboardUrl: URL | null;
4192
+ dashboardLinkText: string;
4193
+ ackUrl: URL;
4194
+ }): Array<WorkspaceMessageBlock> {
4195
+ const lines: Array<string> = [
4196
+ `🚨 **${data.headline}**`,
4197
+ "",
4198
+ `📋 **${data.identifier}**`,
4199
+ "",
4200
+ "👤 You're getting this because you're on call.",
4201
+ ];
4202
+
4203
+ if (data.dashboardUrl) {
4204
+ lines.push(
4205
+ "",
4206
+ `🔎 [${data.dashboardLinkText}](${data.dashboardUrl.toString()})`,
4207
+ );
4208
+ }
4209
+
4210
+ lines.push("", `✅ [Acknowledge](${data.ackUrl.toString()})`);
4211
+
4212
+ const markdownBlock: WorkspacePayloadMarkdown = {
4213
+ _type: "WorkspacePayloadMarkdown",
4214
+ text: lines.join("\n"),
4215
+ };
4216
+
4217
+ return [markdownBlock];
4218
+ }
4219
+
4220
+ @CaptureSpan()
4221
+ public async generateWorkspaceMessageBlocksForAlertCreated(
4222
+ alert: Alert,
4223
+ userOnCallLogTimelineId: ObjectID,
4224
+ ): Promise<Array<WorkspaceMessageBlock>> {
4225
+ const ackUrl: URL = await this.buildOnCallAcknowledgeShortUrl(
4226
+ userOnCallLogTimelineId,
4227
+ );
4228
+
4229
+ const alertIdentifier: string =
4230
+ alert.alertNumber !== undefined
4231
+ ? `${alert.alertNumberWithPrefix || "#" + alert.alertNumber} — ${alert.title || "Alert"}`
4232
+ : alert.title || "Alert";
4233
+
4234
+ let dashboardUrl: URL | null = null;
4235
+
4236
+ if (alert.projectId && alert.id) {
4237
+ dashboardUrl = await AlertService.getAlertLinkInDashboard(
4238
+ alert.projectId,
4239
+ alert.id,
4240
+ );
4241
+ }
4242
+
4243
+ return this.buildWorkspaceMessageBlocks({
4244
+ headline: "New alert assigned to you",
4245
+ identifier: alertIdentifier,
4246
+ dashboardUrl: dashboardUrl,
4247
+ dashboardLinkText: "View alert in OneUptime",
4248
+ ackUrl: ackUrl,
4249
+ });
4250
+ }
4251
+
4252
+ @CaptureSpan()
4253
+ public async generateWorkspaceMessageBlocksForIncidentCreated(
4254
+ incident: Incident,
4255
+ userOnCallLogTimelineId: ObjectID,
4256
+ ): Promise<Array<WorkspaceMessageBlock>> {
4257
+ const ackUrl: URL = await this.buildOnCallAcknowledgeShortUrl(
4258
+ userOnCallLogTimelineId,
4259
+ );
4260
+
4261
+ const incidentIdentifier: string =
4262
+ incident.incidentNumber !== undefined
4263
+ ? `${incident.incidentNumberWithPrefix || "#" + incident.incidentNumber} — ${incident.title || "Incident"}`
4264
+ : incident.title || "Incident";
4265
+
4266
+ let dashboardUrl: URL | null = null;
4267
+
4268
+ if (incident.projectId && incident.id) {
4269
+ dashboardUrl = await IncidentService.getIncidentLinkInDashboard(
4270
+ incident.projectId,
4271
+ incident.id,
4272
+ );
4273
+ }
4274
+
4275
+ return this.buildWorkspaceMessageBlocks({
4276
+ headline: "New incident assigned to you",
4277
+ identifier: incidentIdentifier,
4278
+ dashboardUrl: dashboardUrl,
4279
+ dashboardLinkText: "View incident in OneUptime",
4280
+ ackUrl: ackUrl,
4281
+ });
4282
+ }
4283
+
4284
+ @CaptureSpan()
4285
+ public async generateWorkspaceMessageBlocksForAlertEpisodeCreated(
4286
+ alertEpisode: AlertEpisode,
4287
+ userOnCallLogTimelineId: ObjectID,
4288
+ ): Promise<Array<WorkspaceMessageBlock>> {
4289
+ const ackUrl: URL = await this.buildOnCallAcknowledgeShortUrl(
4290
+ userOnCallLogTimelineId,
4291
+ );
4292
+
4293
+ const episodeIdentifier: string = alertEpisode.episodeNumberWithPrefix
4294
+ ? `${alertEpisode.episodeNumberWithPrefix} — ${alertEpisode.title || "Alert Episode"}`
4295
+ : alertEpisode.episodeNumber !== undefined
4296
+ ? `#${alertEpisode.episodeNumber} — ${alertEpisode.title || "Alert Episode"}`
4297
+ : alertEpisode.title || "Alert Episode";
4298
+
4299
+ let dashboardUrl: URL | null = null;
4300
+
4301
+ if (alertEpisode.projectId && alertEpisode.id) {
4302
+ dashboardUrl = await AlertEpisodeService.getEpisodeLinkInDashboard(
4303
+ alertEpisode.projectId,
4304
+ alertEpisode.id,
4305
+ );
4306
+ }
4307
+
4308
+ return this.buildWorkspaceMessageBlocks({
4309
+ headline: "New alert episode assigned to you",
4310
+ identifier: episodeIdentifier,
4311
+ dashboardUrl: dashboardUrl,
4312
+ dashboardLinkText: "View alert episode in OneUptime",
4313
+ ackUrl: ackUrl,
4314
+ });
4315
+ }
4316
+
4317
+ @CaptureSpan()
4318
+ public async generateWorkspaceMessageBlocksForIncidentEpisodeCreated(
4319
+ incidentEpisode: IncidentEpisode,
4320
+ userOnCallLogTimelineId: ObjectID,
4321
+ ): Promise<Array<WorkspaceMessageBlock>> {
4322
+ const ackUrl: URL = await this.buildOnCallAcknowledgeShortUrl(
4323
+ userOnCallLogTimelineId,
4324
+ );
4325
+
4326
+ const episodeIdentifier: string = incidentEpisode.episodeNumberWithPrefix
4327
+ ? `${incidentEpisode.episodeNumberWithPrefix} — ${incidentEpisode.title || "Incident Episode"}`
4328
+ : incidentEpisode.episodeNumber !== undefined
4329
+ ? `#${incidentEpisode.episodeNumber} — ${incidentEpisode.title || "Incident Episode"}`
4330
+ : incidentEpisode.title || "Incident Episode";
4331
+
4332
+ let dashboardUrl: URL | null = null;
4333
+
4334
+ if (incidentEpisode.projectId && incidentEpisode.id) {
4335
+ dashboardUrl = await IncidentEpisodeService.getEpisodeLinkInDashboard(
4336
+ incidentEpisode.projectId,
4337
+ incidentEpisode.id,
4338
+ );
4339
+ }
4340
+
4341
+ return this.buildWorkspaceMessageBlocks({
4342
+ headline: "New incident episode assigned to you",
4343
+ identifier: episodeIdentifier,
4344
+ dashboardUrl: dashboardUrl,
4345
+ dashboardLinkText: "View incident episode in OneUptime",
4346
+ ackUrl: ackUrl,
4347
+ });
4348
+ }
4349
+
3812
4350
  @CaptureSpan()
3813
4351
  public async generateWhatsAppTemplateForAlertCreated(
3814
4352
  to: Phone,
@@ -4722,7 +5260,7 @@ export class Service extends DatabaseService<Model> {
4722
5260
 
4723
5261
  if (!data.isOptOut && !data.hasNotificationMethod) {
4724
5262
  throw new BadDataException(
4725
- "Call, SMS, WhatsApp, Telegram, Webhook, Email, or Push notification is required",
5263
+ "Call, SMS, WhatsApp, Telegram, Slack, Microsoft Teams, Webhook, Email, or Push notification is required",
4726
5264
  );
4727
5265
  }
4728
5266
  }
@@ -5021,6 +5559,8 @@ export class Service extends DatabaseService<Model> {
5021
5559
  userCallId: true,
5022
5560
  userWhatsAppId: true,
5023
5561
  userTelegramId: true,
5562
+ userSlackId: true,
5563
+ userMicrosoftTeamsId: true,
5024
5564
  userPushId: true,
5025
5565
  userWebhookId: true,
5026
5566
  },
@@ -5274,6 +5814,8 @@ export class Service extends DatabaseService<Model> {
5274
5814
  userCallId: true,
5275
5815
  userWhatsAppId: true,
5276
5816
  userTelegramId: true,
5817
+ userSlackId: true,
5818
+ userMicrosoftTeamsId: true,
5277
5819
  userPushId: true,
5278
5820
  userWebhookId: true,
5279
5821
  },
@@ -5439,6 +5981,12 @@ export class Service extends DatabaseService<Model> {
5439
5981
  if (descriptor.userTelegramId) {
5440
5982
  rule.userTelegramId = descriptor.userTelegramId;
5441
5983
  }
5984
+ if (descriptor.userSlackId) {
5985
+ rule.userSlackId = descriptor.userSlackId;
5986
+ }
5987
+ if (descriptor.userMicrosoftTeamsId) {
5988
+ rule.userMicrosoftTeamsId = descriptor.userMicrosoftTeamsId;
5989
+ }
5442
5990
  if (descriptor.userWebhookId) {
5443
5991
  rule.userWebhookId = descriptor.userWebhookId;
5444
5992
  }
@@ -5466,6 +6014,12 @@ export class Service extends DatabaseService<Model> {
5466
6014
  if (descriptor.userTelegramId) {
5467
6015
  query["userTelegramId"] = descriptor.userTelegramId;
5468
6016
  }
6017
+ if (descriptor.userSlackId) {
6018
+ query["userSlackId"] = descriptor.userSlackId;
6019
+ }
6020
+ if (descriptor.userMicrosoftTeamsId) {
6021
+ query["userMicrosoftTeamsId"] = descriptor.userMicrosoftTeamsId;
6022
+ }
5469
6023
  if (descriptor.userWebhookId) {
5470
6024
  query["userWebhookId"] = descriptor.userWebhookId;
5471
6025
  }
@@ -5834,6 +6388,20 @@ export class Service extends DatabaseService<Model> {
5834
6388
  props: props,
5835
6389
  });
5836
6390
  isVerified = Boolean(row?.isVerified);
6391
+ } else if (data.methodType === ReadinessMethodType.Slack) {
6392
+ row = await UserSlackService.findOneBy({
6393
+ query: query,
6394
+ select: { _id: true, userId: true, isVerified: true },
6395
+ props: props,
6396
+ });
6397
+ isVerified = Boolean(row?.isVerified);
6398
+ } else if (data.methodType === ReadinessMethodType.MicrosoftTeams) {
6399
+ row = await UserMicrosoftTeamsService.findOneBy({
6400
+ query: query,
6401
+ select: { _id: true, userId: true, isVerified: true },
6402
+ props: props,
6403
+ });
6404
+ isVerified = Boolean(row?.isVerified);
5837
6405
  } else if (data.methodType === ReadinessMethodType.Webhook) {
5838
6406
  row = await UserWebhookService.findOneBy({
5839
6407
  query: query,
@@ -5893,6 +6461,14 @@ export class Service extends DatabaseService<Model> {
5893
6461
  return rule.userTelegramId;
5894
6462
  }
5895
6463
 
6464
+ if (methodType === ReadinessMethodType.Slack) {
6465
+ return rule.userSlackId;
6466
+ }
6467
+
6468
+ if (methodType === ReadinessMethodType.MicrosoftTeams) {
6469
+ return rule.userMicrosoftTeamsId;
6470
+ }
6471
+
5896
6472
  if (methodType === ReadinessMethodType.Webhook) {
5897
6473
  return rule.userWebhookId;
5898
6474
  }
@@ -6227,6 +6803,8 @@ export class Service extends DatabaseService<Model> {
6227
6803
  userPushId: true,
6228
6804
  userWhatsAppId: true,
6229
6805
  userTelegramId: true,
6806
+ userSlackId: true,
6807
+ userMicrosoftTeamsId: true,
6230
6808
  userWebhookId: true,
6231
6809
  },
6232
6810
  sort: {