@oneuptime/common 7.0.3718 → 7.0.3786

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 (201) hide show
  1. package/Models/DatabaseModels/Alert.ts +3 -2
  2. package/Models/DatabaseModels/Incident.ts +3 -2
  3. package/Models/DatabaseModels/Index.ts +3 -0
  4. package/Models/DatabaseModels/ProjectUser.ts +335 -0
  5. package/Models/DatabaseModels/ScheduledMaintenance.ts +3 -2
  6. package/Server/API/SlackAPI.ts +65 -97
  7. package/Server/Infrastructure/Postgres/SchemaMigrations/1740597525803-MigrationName.ts +17 -0
  8. package/Server/Infrastructure/Postgres/SchemaMigrations/1740598793630-MigrationName.ts +17 -0
  9. package/Server/Infrastructure/Postgres/SchemaMigrations/1741031019972-MigrationName.ts +17 -0
  10. package/Server/Infrastructure/Postgres/SchemaMigrations/1741209339971-MigrationName.ts +101 -0
  11. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +8 -0
  12. package/Server/Middleware/SlackAuthorization.ts +11 -2
  13. package/Server/Services/AlertFeedService.ts +2 -2
  14. package/Server/Services/AlertInternalNoteService.ts +2 -2
  15. package/Server/Services/AlertOwnerTeamService.ts +4 -4
  16. package/Server/Services/AlertOwnerUserService.ts +3 -3
  17. package/Server/Services/AlertService.ts +62 -20
  18. package/Server/Services/AlertStateTimelineService.ts +8 -18
  19. package/Server/Services/IncidentFeedService.ts +101 -2
  20. package/Server/Services/IncidentInternalNoteService.ts +47 -4
  21. package/Server/Services/IncidentOwnerTeamService.ts +57 -4
  22. package/Server/Services/IncidentOwnerUserService.ts +59 -15
  23. package/Server/Services/IncidentPublicNoteService.ts +41 -4
  24. package/Server/Services/IncidentService.ts +279 -193
  25. package/Server/Services/IncidentStateService.ts +25 -0
  26. package/Server/Services/IncidentStateTimelineService.ts +37 -19
  27. package/Server/Services/MonitorStatusTimelineService.ts +7 -17
  28. package/Server/Services/OnCallDutyPolicyEscalationRuleService.ts +2 -0
  29. package/Server/Services/OnCallDutyPolicyExecutionLogService.ts +74 -7
  30. package/Server/Services/OnCallDutyPolicyExecutionLogTimelineService.ts +63 -4
  31. package/Server/Services/OnCallDutyPolicyService.ts +13 -0
  32. package/Server/Services/ProjectUserService.ts +130 -0
  33. package/Server/Services/ScheduledMaintenanceFeedService.ts +2 -2
  34. package/Server/Services/ScheduledMaintenanceInternalNoteService.ts +12 -10
  35. package/Server/Services/ScheduledMaintenanceOwnerTeamService.ts +22 -18
  36. package/Server/Services/ScheduledMaintenanceOwnerUserService.ts +28 -30
  37. package/Server/Services/ScheduledMaintenancePublicNoteService.ts +12 -10
  38. package/Server/Services/ScheduledMaintenanceService.ts +16 -10
  39. package/Server/Services/ScheduledMaintenanceStateTimelineService.ts +1 -1
  40. package/Server/Services/StatusPageSubscriberService.ts +3 -0
  41. package/Server/Services/TeamMemberService.ts +20 -0
  42. package/Server/Services/UserNotificationRuleService.ts +74 -0
  43. package/Server/Services/UserOnCallLogService.ts +1 -1
  44. package/Server/Services/UserService.ts +35 -0
  45. package/Server/Services/WorkspaceNotificationRuleService.ts +508 -149
  46. package/Server/Services/WorkspaceUserAuthTokenService.ts +23 -0
  47. package/Server/Utils/Express.ts +1 -1
  48. package/Server/Utils/StartServer.ts +6 -1
  49. package/Server/Utils/Workspace/MicrosoftTeams/Messages/Incident.ts +195 -0
  50. package/Server/Utils/Workspace/Slack/Actions/ActionTypes.ts +20 -0
  51. package/Server/Utils/Workspace/Slack/Actions/Auth.ts +266 -0
  52. package/Server/Utils/Workspace/Slack/Actions/Incident.ts +1117 -0
  53. package/Server/Utils/Workspace/Slack/Messages/Incident.ts +116 -0
  54. package/Server/Utils/Workspace/Slack/Slack.ts +555 -18
  55. package/Server/Utils/Workspace/Slack/app-manifest.json +18 -10
  56. package/Server/Utils/Workspace/Workspace.ts +194 -1
  57. package/Server/Utils/Workspace/WorkspaceBase.ts +145 -19
  58. package/Server/Utils/Workspace/WorkspaceMessages/Incident.ts +68 -0
  59. package/Types/Icon/IconProp.ts +1 -0
  60. package/Types/Workspace/NotificationRules/NotificationRuleCondition.ts +2 -1
  61. package/Types/Workspace/NotificationRules/NotificationRuleUtil.ts +251 -121
  62. package/Types/Workspace/NotificationRules/NotificationRuleWorkspaceChannel.ts +6 -0
  63. package/Types/Workspace/WorkspaceMessagePayload.ts +71 -2
  64. package/UI/Components/ComingSoon/ComingSoon.tsx +13 -3
  65. package/UI/Components/Forms/Fields/FormField.tsx +2 -2
  66. package/UI/Components/Icon/Icon.tsx +39 -2
  67. package/UI/Components/ModelTable/BaseModelTable.tsx +16 -0
  68. package/UI/Components/Radio/Radio.tsx +11 -2
  69. package/UI/Components/Table/TableCard.tsx +2 -2
  70. package/build/dist/Models/DatabaseModels/Alert.js.map +1 -1
  71. package/build/dist/Models/DatabaseModels/Incident.js.map +1 -1
  72. package/build/dist/Models/DatabaseModels/Index.js +2 -0
  73. package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
  74. package/build/dist/Models/DatabaseModels/ProjectUser.js +340 -0
  75. package/build/dist/Models/DatabaseModels/ProjectUser.js.map +1 -0
  76. package/build/dist/Models/DatabaseModels/ScheduledMaintenance.js.map +1 -1
  77. package/build/dist/Server/API/SlackAPI.js +39 -79
  78. package/build/dist/Server/API/SlackAPI.js.map +1 -1
  79. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1740597525803-MigrationName.js +12 -0
  80. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1740597525803-MigrationName.js.map +1 -0
  81. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1740598793630-MigrationName.js +12 -0
  82. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1740598793630-MigrationName.js.map +1 -0
  83. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1741031019972-MigrationName.js +12 -0
  84. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1741031019972-MigrationName.js.map +1 -0
  85. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1741209339971-MigrationName.js +42 -0
  86. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1741209339971-MigrationName.js.map +1 -0
  87. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +8 -0
  88. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  89. package/build/dist/Server/Middleware/SlackAuthorization.js +8 -2
  90. package/build/dist/Server/Middleware/SlackAuthorization.js.map +1 -1
  91. package/build/dist/Server/Services/AlertFeedService.js +2 -2
  92. package/build/dist/Server/Services/AlertFeedService.js.map +1 -1
  93. package/build/dist/Server/Services/AlertInternalNoteService.js +2 -2
  94. package/build/dist/Server/Services/AlertInternalNoteService.js.map +1 -1
  95. package/build/dist/Server/Services/AlertOwnerTeamService.js +4 -4
  96. package/build/dist/Server/Services/AlertOwnerTeamService.js.map +1 -1
  97. package/build/dist/Server/Services/AlertOwnerUserService.js +3 -3
  98. package/build/dist/Server/Services/AlertOwnerUserService.js.map +1 -1
  99. package/build/dist/Server/Services/AlertService.js +44 -19
  100. package/build/dist/Server/Services/AlertService.js.map +1 -1
  101. package/build/dist/Server/Services/AlertStateTimelineService.js +6 -16
  102. package/build/dist/Server/Services/AlertStateTimelineService.js.map +1 -1
  103. package/build/dist/Server/Services/IncidentFeedService.js +62 -2
  104. package/build/dist/Server/Services/IncidentFeedService.js.map +1 -1
  105. package/build/dist/Server/Services/IncidentInternalNoteService.js +35 -4
  106. package/build/dist/Server/Services/IncidentInternalNoteService.js.map +1 -1
  107. package/build/dist/Server/Services/IncidentOwnerTeamService.js +42 -4
  108. package/build/dist/Server/Services/IncidentOwnerTeamService.js.map +1 -1
  109. package/build/dist/Server/Services/IncidentOwnerUserService.js +43 -15
  110. package/build/dist/Server/Services/IncidentOwnerUserService.js.map +1 -1
  111. package/build/dist/Server/Services/IncidentPublicNoteService.js +32 -4
  112. package/build/dist/Server/Services/IncidentPublicNoteService.js.map +1 -1
  113. package/build/dist/Server/Services/IncidentService.js +221 -170
  114. package/build/dist/Server/Services/IncidentService.js.map +1 -1
  115. package/build/dist/Server/Services/IncidentStateService.js +14 -0
  116. package/build/dist/Server/Services/IncidentStateService.js.map +1 -1
  117. package/build/dist/Server/Services/IncidentStateTimelineService.js +31 -17
  118. package/build/dist/Server/Services/IncidentStateTimelineService.js.map +1 -1
  119. package/build/dist/Server/Services/MonitorStatusTimelineService.js +5 -15
  120. package/build/dist/Server/Services/MonitorStatusTimelineService.js.map +1 -1
  121. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleService.js +1 -0
  122. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleService.js.map +1 -1
  123. package/build/dist/Server/Services/OnCallDutyPolicyExecutionLogService.js +62 -7
  124. package/build/dist/Server/Services/OnCallDutyPolicyExecutionLogService.js.map +1 -1
  125. package/build/dist/Server/Services/OnCallDutyPolicyExecutionLogTimelineService.js +51 -5
  126. package/build/dist/Server/Services/OnCallDutyPolicyExecutionLogTimelineService.js.map +1 -1
  127. package/build/dist/Server/Services/OnCallDutyPolicyService.js +6 -0
  128. package/build/dist/Server/Services/OnCallDutyPolicyService.js.map +1 -1
  129. package/build/dist/Server/Services/ProjectUserService.js +106 -0
  130. package/build/dist/Server/Services/ProjectUserService.js.map +1 -0
  131. package/build/dist/Server/Services/ScheduledMaintenanceFeedService.js +2 -2
  132. package/build/dist/Server/Services/ScheduledMaintenanceFeedService.js.map +1 -1
  133. package/build/dist/Server/Services/ScheduledMaintenanceInternalNoteService.js +2 -2
  134. package/build/dist/Server/Services/ScheduledMaintenanceInternalNoteService.js.map +1 -1
  135. package/build/dist/Server/Services/ScheduledMaintenanceOwnerTeamService.js +4 -4
  136. package/build/dist/Server/Services/ScheduledMaintenanceOwnerTeamService.js.map +1 -1
  137. package/build/dist/Server/Services/ScheduledMaintenanceOwnerUserService.js +8 -16
  138. package/build/dist/Server/Services/ScheduledMaintenanceOwnerUserService.js.map +1 -1
  139. package/build/dist/Server/Services/ScheduledMaintenancePublicNoteService.js +2 -2
  140. package/build/dist/Server/Services/ScheduledMaintenancePublicNoteService.js.map +1 -1
  141. package/build/dist/Server/Services/ScheduledMaintenanceService.js +5 -2
  142. package/build/dist/Server/Services/ScheduledMaintenanceService.js.map +1 -1
  143. package/build/dist/Server/Services/ScheduledMaintenanceStateTimelineService.js +1 -1
  144. package/build/dist/Server/Services/ScheduledMaintenanceStateTimelineService.js.map +1 -1
  145. package/build/dist/Server/Services/StatusPageSubscriberService.js +3 -0
  146. package/build/dist/Server/Services/StatusPageSubscriberService.js.map +1 -1
  147. package/build/dist/Server/Services/TeamMemberService.js +17 -0
  148. package/build/dist/Server/Services/TeamMemberService.js.map +1 -1
  149. package/build/dist/Server/Services/UserNotificationRuleService.js +52 -0
  150. package/build/dist/Server/Services/UserNotificationRuleService.js.map +1 -1
  151. package/build/dist/Server/Services/UserOnCallLogService.js +1 -1
  152. package/build/dist/Server/Services/UserOnCallLogService.js.map +1 -1
  153. package/build/dist/Server/Services/UserService.js +23 -0
  154. package/build/dist/Server/Services/UserService.js.map +1 -1
  155. package/build/dist/Server/Services/WorkspaceNotificationRuleService.js +306 -84
  156. package/build/dist/Server/Services/WorkspaceNotificationRuleService.js.map +1 -1
  157. package/build/dist/Server/Services/WorkspaceUserAuthTokenService.js +18 -0
  158. package/build/dist/Server/Services/WorkspaceUserAuthTokenService.js.map +1 -1
  159. package/build/dist/Server/Utils/StartServer.js +4 -0
  160. package/build/dist/Server/Utils/StartServer.js.map +1 -1
  161. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Messages/Incident.js +148 -0
  162. package/build/dist/Server/Utils/Workspace/MicrosoftTeams/Messages/Incident.js.map +1 -0
  163. package/build/dist/Server/Utils/Workspace/Slack/Actions/ActionTypes.js +19 -0
  164. package/build/dist/Server/Utils/Workspace/Slack/Actions/ActionTypes.js.map +1 -0
  165. package/build/dist/Server/Utils/Workspace/Slack/Actions/Auth.js +167 -0
  166. package/build/dist/Server/Utils/Workspace/Slack/Actions/Auth.js.map +1 -0
  167. package/build/dist/Server/Utils/Workspace/Slack/Actions/Incident.js +727 -0
  168. package/build/dist/Server/Utils/Workspace/Slack/Actions/Incident.js.map +1 -0
  169. package/build/dist/Server/Utils/Workspace/Slack/Messages/Incident.js +82 -0
  170. package/build/dist/Server/Utils/Workspace/Slack/Messages/Incident.js.map +1 -0
  171. package/build/dist/Server/Utils/Workspace/Slack/Slack.js +397 -14
  172. package/build/dist/Server/Utils/Workspace/Slack/Slack.js.map +1 -1
  173. package/build/dist/Server/Utils/Workspace/Slack/app-manifest.json +18 -10
  174. package/build/dist/Server/Utils/Workspace/Workspace.js +126 -0
  175. package/build/dist/Server/Utils/Workspace/Workspace.js.map +1 -1
  176. package/build/dist/Server/Utils/Workspace/WorkspaceBase.js +69 -11
  177. package/build/dist/Server/Utils/Workspace/WorkspaceBase.js.map +1 -1
  178. package/build/dist/Server/Utils/Workspace/WorkspaceMessages/Incident.js +47 -0
  179. package/build/dist/Server/Utils/Workspace/WorkspaceMessages/Incident.js.map +1 -0
  180. package/build/dist/Types/Icon/IconProp.js +1 -0
  181. package/build/dist/Types/Icon/IconProp.js.map +1 -1
  182. package/build/dist/Types/Workspace/NotificationRules/NotificationRuleCondition.js +2 -1
  183. package/build/dist/Types/Workspace/NotificationRules/NotificationRuleCondition.js.map +1 -1
  184. package/build/dist/Types/Workspace/NotificationRules/NotificationRuleUtil.js +214 -120
  185. package/build/dist/Types/Workspace/NotificationRules/NotificationRuleUtil.js.map +1 -1
  186. package/build/dist/Types/Workspace/NotificationRules/NotificationRuleWorkspaceChannel.js +2 -0
  187. package/build/dist/Types/Workspace/NotificationRules/NotificationRuleWorkspaceChannel.js.map +1 -0
  188. package/build/dist/UI/Components/ComingSoon/ComingSoon.js +3 -2
  189. package/build/dist/UI/Components/ComingSoon/ComingSoon.js.map +1 -1
  190. package/build/dist/UI/Components/Forms/Fields/FormField.js +2 -2
  191. package/build/dist/UI/Components/Forms/Fields/FormField.js.map +1 -1
  192. package/build/dist/UI/Components/Icon/Icon.js +19 -2
  193. package/build/dist/UI/Components/Icon/Icon.js.map +1 -1
  194. package/build/dist/UI/Components/ModelTable/BaseModelTable.js +11 -0
  195. package/build/dist/UI/Components/ModelTable/BaseModelTable.js.map +1 -1
  196. package/build/dist/UI/Components/Radio/Radio.js +5 -2
  197. package/build/dist/UI/Components/Radio/Radio.js.map +1 -1
  198. package/build/dist/UI/Components/Table/TableCard.js +2 -2
  199. package/build/dist/UI/Components/Table/TableCard.js.map +1 -1
  200. package/package.json +3 -2
  201. package/Server/Utils/Workspace/Slack/app-manifest.example.json +0 -198
@@ -0,0 +1,101 @@
1
+ import { MigrationInterface, QueryRunner } from "typeorm";
2
+
3
+ export class MigrationName1741209339971 implements MigrationInterface {
4
+ public name = "MigrationName1741209339971";
5
+
6
+ public async up(queryRunner: QueryRunner): Promise<void> {
7
+ await queryRunner.query(
8
+ `CREATE TABLE "ProjectUser" ("_id" uuid NOT NULL DEFAULT uuid_generate_v4(), "createdAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "updatedAt" TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT now(), "deletedAt" TIMESTAMP WITH TIME ZONE, "version" integer NOT NULL, "projectId" uuid NOT NULL, "userId" uuid NOT NULL, "createdByUserId" uuid, "deletedByUserId" uuid, CONSTRAINT "PK_912199af7fc0be254b07b37306b" PRIMARY KEY ("_id"))`,
9
+ );
10
+ await queryRunner.query(
11
+ `CREATE INDEX "IDX_770271904cf388001552bc4755" ON "ProjectUser" ("projectId") `,
12
+ );
13
+ await queryRunner.query(
14
+ `CREATE TABLE "ProjectUserAcceptedTeams" ("projectUserId" uuid NOT NULL, "teamId" uuid NOT NULL, CONSTRAINT "PK_93ca44f68c74f4a859f2bcf260f" PRIMARY KEY ("projectUserId", "teamId"))`,
15
+ );
16
+ await queryRunner.query(
17
+ `CREATE INDEX "IDX_54f5c1c6cf385ffa6094430027" ON "ProjectUserAcceptedTeams" ("projectUserId") `,
18
+ );
19
+ await queryRunner.query(
20
+ `CREATE INDEX "IDX_e1731fb8a4540127d98fd28796" ON "ProjectUserAcceptedTeams" ("teamId") `,
21
+ );
22
+ await queryRunner.query(
23
+ `CREATE TABLE "ProjectUserInvitedTeams" ("projectUserId" uuid NOT NULL, "teamId" uuid NOT NULL, CONSTRAINT "PK_59cc028549a2c4e35005277a507" PRIMARY KEY ("projectUserId", "teamId"))`,
24
+ );
25
+ await queryRunner.query(
26
+ `CREATE INDEX "IDX_baa3a99d9c899e2e59c545e288" ON "ProjectUserInvitedTeams" ("projectUserId") `,
27
+ );
28
+ await queryRunner.query(
29
+ `CREATE INDEX "IDX_aa26c583621dab66eebfba67a4" ON "ProjectUserInvitedTeams" ("teamId") `,
30
+ );
31
+ await queryRunner.query(
32
+ `ALTER TABLE "ProjectUser" ADD CONSTRAINT "FK_770271904cf388001552bc47559" FOREIGN KEY ("projectId") REFERENCES "Project"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
33
+ );
34
+ await queryRunner.query(
35
+ `ALTER TABLE "ProjectUser" ADD CONSTRAINT "FK_b2a608caefe7d8206517083d856" FOREIGN KEY ("userId") REFERENCES "User"("_id") ON DELETE CASCADE ON UPDATE NO ACTION`,
36
+ );
37
+ await queryRunner.query(
38
+ `ALTER TABLE "ProjectUser" ADD CONSTRAINT "FK_c4aa1af08370547825f1c76f70a" FOREIGN KEY ("createdByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
39
+ );
40
+ await queryRunner.query(
41
+ `ALTER TABLE "ProjectUser" ADD CONSTRAINT "FK_4a79e6f07a902e997f254c8c7eb" FOREIGN KEY ("deletedByUserId") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
42
+ );
43
+ await queryRunner.query(
44
+ `ALTER TABLE "ProjectUserAcceptedTeams" ADD CONSTRAINT "FK_54f5c1c6cf385ffa60944300270" FOREIGN KEY ("projectUserId") REFERENCES "ProjectUser"("_id") ON DELETE CASCADE ON UPDATE CASCADE`,
45
+ );
46
+ await queryRunner.query(
47
+ `ALTER TABLE "ProjectUserAcceptedTeams" ADD CONSTRAINT "FK_e1731fb8a4540127d98fd28796c" FOREIGN KEY ("teamId") REFERENCES "Team"("_id") ON DELETE CASCADE ON UPDATE CASCADE`,
48
+ );
49
+ await queryRunner.query(
50
+ `ALTER TABLE "ProjectUserInvitedTeams" ADD CONSTRAINT "FK_baa3a99d9c899e2e59c545e288b" FOREIGN KEY ("projectUserId") REFERENCES "ProjectUser"("_id") ON DELETE CASCADE ON UPDATE CASCADE`,
51
+ );
52
+ await queryRunner.query(
53
+ `ALTER TABLE "ProjectUserInvitedTeams" ADD CONSTRAINT "FK_aa26c583621dab66eebfba67a44" FOREIGN KEY ("teamId") REFERENCES "Team"("_id") ON DELETE CASCADE ON UPDATE CASCADE`,
54
+ );
55
+ }
56
+
57
+ public async down(queryRunner: QueryRunner): Promise<void> {
58
+ await queryRunner.query(
59
+ `ALTER TABLE "ProjectUserInvitedTeams" DROP CONSTRAINT "FK_aa26c583621dab66eebfba67a44"`,
60
+ );
61
+ await queryRunner.query(
62
+ `ALTER TABLE "ProjectUserInvitedTeams" DROP CONSTRAINT "FK_baa3a99d9c899e2e59c545e288b"`,
63
+ );
64
+ await queryRunner.query(
65
+ `ALTER TABLE "ProjectUserAcceptedTeams" DROP CONSTRAINT "FK_e1731fb8a4540127d98fd28796c"`,
66
+ );
67
+ await queryRunner.query(
68
+ `ALTER TABLE "ProjectUserAcceptedTeams" DROP CONSTRAINT "FK_54f5c1c6cf385ffa60944300270"`,
69
+ );
70
+ await queryRunner.query(
71
+ `ALTER TABLE "ProjectUser" DROP CONSTRAINT "FK_4a79e6f07a902e997f254c8c7eb"`,
72
+ );
73
+ await queryRunner.query(
74
+ `ALTER TABLE "ProjectUser" DROP CONSTRAINT "FK_c4aa1af08370547825f1c76f70a"`,
75
+ );
76
+ await queryRunner.query(
77
+ `ALTER TABLE "ProjectUser" DROP CONSTRAINT "FK_b2a608caefe7d8206517083d856"`,
78
+ );
79
+ await queryRunner.query(
80
+ `ALTER TABLE "ProjectUser" DROP CONSTRAINT "FK_770271904cf388001552bc47559"`,
81
+ );
82
+ await queryRunner.query(
83
+ `DROP INDEX "public"."IDX_aa26c583621dab66eebfba67a4"`,
84
+ );
85
+ await queryRunner.query(
86
+ `DROP INDEX "public"."IDX_baa3a99d9c899e2e59c545e288"`,
87
+ );
88
+ await queryRunner.query(`DROP TABLE "ProjectUserInvitedTeams"`);
89
+ await queryRunner.query(
90
+ `DROP INDEX "public"."IDX_e1731fb8a4540127d98fd28796"`,
91
+ );
92
+ await queryRunner.query(
93
+ `DROP INDEX "public"."IDX_54f5c1c6cf385ffa6094430027"`,
94
+ );
95
+ await queryRunner.query(`DROP TABLE "ProjectUserAcceptedTeams"`);
96
+ await queryRunner.query(
97
+ `DROP INDEX "public"."IDX_770271904cf388001552bc4755"`,
98
+ );
99
+ await queryRunner.query(`DROP TABLE "ProjectUser"`);
100
+ }
101
+ }
@@ -108,6 +108,10 @@ import { MigrationName1739569321582 } from "./1739569321582-MigrationName";
108
108
  import { MigrationName1740164199817 } from "./1740164199817-MigrationName";
109
109
  import { MigrationName1740419151825 } from "./1740419151825-MigrationName";
110
110
  import { MigrationName1740430229844 } from "./1740430229844-MigrationName";
111
+ import { MigrationName1740597525803 } from "./1740597525803-MigrationName";
112
+ import { MigrationName1740598793630 } from "./1740598793630-MigrationName";
113
+ import { MigrationName1741031019972 } from "./1741031019972-MigrationName";
114
+ import { MigrationName1741209339971 } from "./1741209339971-MigrationName";
111
115
 
112
116
  export default [
113
117
  InitialMigration,
@@ -220,4 +224,8 @@ export default [
220
224
  MigrationName1740164199817,
221
225
  MigrationName1740419151825,
222
226
  MigrationName1740430229844,
227
+ MigrationName1740597525803,
228
+ MigrationName1740598793630,
229
+ MigrationName1741031019972,
230
+ MigrationName1741209339971,
223
231
  ];
@@ -15,7 +15,10 @@ export default class SlackAuthorization {
15
15
  res: ExpressResponse,
16
16
  next: NextFunction,
17
17
  ): Promise<void> {
18
+ logger.debug("Starting Slack request authorization");
19
+
18
20
  if (!SlackAppSigningSecret) {
21
+ logger.error("SLACK_APP_SIGNING_SECRET env variable not found.");
19
22
  return Response.sendErrorResponse(
20
23
  req,
21
24
  res,
@@ -32,15 +35,19 @@ export default class SlackAuthorization {
32
35
  const timestamp: string = req.headers[
33
36
  "x-slack-request-timestamp"
34
37
  ] as string;
35
- const requestBody: string = req.body;
38
+ const requestBody: string =
39
+ (req as OneUptimeRequest).rawFormUrlEncodedBody || "";
36
40
 
37
41
  logger.debug(`slackSignature: ${slackSignature}`);
38
42
  logger.debug(`timestamp: ${timestamp}`);
39
- logger.debug(`requestBody: ${requestBody}`);
43
+ logger.debug(`requestBody: `);
44
+ logger.debug(requestBody);
40
45
 
41
46
  const baseString: string = `v0:${timestamp}:${requestBody}`;
42
47
  const signature: string = `v0=${crypto.createHmac("sha256", slackSigningSecret).update(baseString).digest("hex")}`;
43
48
 
49
+ logger.debug(`Generated signature: ${signature}`);
50
+
44
51
  // check if the signature is valid
45
52
  if (
46
53
  !crypto.timingSafeEqual(
@@ -48,6 +55,7 @@ export default class SlackAuthorization {
48
55
  Buffer.from(slackSignature),
49
56
  )
50
57
  ) {
58
+ logger.error("Slack Signature Verification Failed.");
51
59
  return Response.sendErrorResponse(
52
60
  req,
53
61
  res,
@@ -55,6 +63,7 @@ export default class SlackAuthorization {
55
63
  );
56
64
  }
57
65
 
66
+ logger.debug("Slack request authorized successfully");
58
67
  next();
59
68
  }
60
69
  }
@@ -19,7 +19,7 @@ export class Service extends DatabaseService<Model> {
19
19
  }
20
20
  }
21
21
 
22
- public async createAlertFeed(data: {
22
+ public async createAlertFeedItem(data: {
23
23
  alertId: ObjectID;
24
24
  feedInfoInMarkdown: string;
25
25
  alertFeedEventType: AlertFeedEventType;
@@ -78,7 +78,7 @@ export class Service extends DatabaseService<Model> {
78
78
  },
79
79
  });
80
80
  } catch (error) {
81
- logger.error("AlertFeedService.createAlertFeed");
81
+ logger.error("AlertFeedService.createAlertFeedItem");
82
82
  logger.error(error);
83
83
  // we dont want to throw the error here, as this is a non-critical operation
84
84
  }
@@ -19,7 +19,7 @@ export class Service extends DatabaseService<Model> {
19
19
  const userId: ObjectID | null | undefined =
20
20
  createdItem.createdByUserId || createdItem.createdByUser?.id;
21
21
 
22
- await AlertFeedService.createAlertFeed({
22
+ await AlertFeedService.createAlertFeedItem({
23
23
  alertId: createdItem.alertId!,
24
24
  projectId: createdItem.projectId!,
25
25
  alertFeedEventType: AlertFeedEventType.PrivateNote,
@@ -62,7 +62,7 @@ export class Service extends DatabaseService<Model> {
62
62
  onUpdate.updateBy.props.userId;
63
63
 
64
64
  for (const updatedItem of updatedItems) {
65
- await AlertFeedService.createAlertFeed({
65
+ await AlertFeedService.createAlertFeedItem({
66
66
  alertId: updatedItem.alertId!,
67
67
  projectId: updatedItem.projectId!,
68
68
  alertFeedEventType: AlertFeedEventType.PrivateNote,
@@ -65,12 +65,12 @@ export class Service extends DatabaseService<Model> {
65
65
  });
66
66
 
67
67
  if (team && team.name) {
68
- await AlertFeedService.createAlertFeed({
68
+ await AlertFeedService.createAlertFeedItem({
69
69
  alertId: alertId,
70
70
  projectId: projectId,
71
71
  alertFeedEventType: AlertFeedEventType.OwnerTeamRemoved,
72
72
  displayColor: Red500,
73
- feedInfoInMarkdown: `**Team ${team.name}** was removed from the alert as the owner.`,
73
+ feedInfoInMarkdown: `Removed team **${team.name}** from the alert as the owner.`,
74
74
  userId: deleteByUserId || undefined,
75
75
  });
76
76
  }
@@ -104,12 +104,12 @@ export class Service extends DatabaseService<Model> {
104
104
  });
105
105
 
106
106
  if (team && team.name) {
107
- await AlertFeedService.createAlertFeed({
107
+ await AlertFeedService.createAlertFeedItem({
108
108
  alertId: alertId,
109
109
  projectId: projectId,
110
110
  alertFeedEventType: AlertFeedEventType.OwnerTeamAdded,
111
111
  displayColor: Gray500,
112
- feedInfoInMarkdown: `**Team ${team.name}** was added to the alert as the owner.`,
112
+ feedInfoInMarkdown: `Added team **${team.name}** to the alert as the owner.`,
113
113
  userId: createdByUserId || undefined,
114
114
  });
115
115
  }
@@ -66,12 +66,12 @@ export class Service extends DatabaseService<Model> {
66
66
  });
67
67
 
68
68
  if (user && user.name) {
69
- await AlertFeedService.createAlertFeed({
69
+ await AlertFeedService.createAlertFeedItem({
70
70
  alertId: alertId,
71
71
  projectId: projectId,
72
72
  alertFeedEventType: AlertFeedEventType.OwnerUserRemoved,
73
73
  displayColor: Red500,
74
- feedInfoInMarkdown: `**${user.name.toString()}** (${user.email?.toString()}) was removed from the alert as the owner.`,
74
+ feedInfoInMarkdown: `Removed **${user.name.toString()}** (${user.email?.toString()}) from the alert as the owner.`,
75
75
  userId: deleteByUserId || undefined,
76
76
  });
77
77
  }
@@ -106,7 +106,7 @@ export class Service extends DatabaseService<Model> {
106
106
  });
107
107
 
108
108
  if (user && user.name) {
109
- await AlertFeedService.createAlertFeed({
109
+ await AlertFeedService.createAlertFeedItem({
110
110
  alertId: alertId,
111
111
  projectId: projectId,
112
112
  alertFeedEventType: AlertFeedEventType.OwnerUserAdded,
@@ -45,6 +45,8 @@ import Label from "../../Models/DatabaseModels/Label";
45
45
  import LabelService from "./LabelService";
46
46
  import AlertSeverity from "../../Models/DatabaseModels/AlertSeverity";
47
47
  import AlertSeverityService from "./AlertSeverityService";
48
+ import WorkspaceType from "../../Types/Workspace/WorkspaceType";
49
+ import NotificationRuleWorkspaceChannel from "../../Types/Workspace/NotificationRules/NotificationRuleWorkspaceChannel";
48
50
 
49
51
  export class Service extends DatabaseService<Model> {
50
52
  public constructor() {
@@ -229,22 +231,13 @@ export class Service extends DatabaseService<Model> {
229
231
  userId = createBy.data.createdByUser.id;
230
232
  }
231
233
 
232
- const user: User | null = await UserService.findOneBy({
233
- query: {
234
- _id: userId?.toString() as string,
235
- },
236
- select: {
237
- _id: true,
238
- name: true,
239
- email: true,
240
- },
241
- props: {
242
- isRoot: true,
243
- },
244
- });
245
-
246
- if (user) {
247
- createBy.data.rootCause = `Alert created by ${user.name} (${user.email})`;
234
+ if (userId) {
235
+ createBy.data.rootCause = `Alert created by ${await UserService.getUserMarkdownString(
236
+ {
237
+ userId: userId!,
238
+ projectId: projectId,
239
+ },
240
+ )}`;
248
241
  }
249
242
  }
250
243
 
@@ -270,7 +263,7 @@ export class Service extends DatabaseService<Model> {
270
263
  const createdByUserId: ObjectID | undefined | null =
271
264
  createdItem.createdByUserId || createdItem.createdByUser?.id;
272
265
 
273
- await AlertFeedService.createAlertFeed({
266
+ await AlertFeedService.createAlertFeedItem({
274
267
  alertId: createdItem.id!,
275
268
  projectId: createdItem.projectId!,
276
269
  alertFeedEventType: AlertFeedEventType.AlertCreated,
@@ -289,7 +282,7 @@ export class Service extends DatabaseService<Model> {
289
282
  userId: createdByUserId || undefined,
290
283
  });
291
284
 
292
- await AlertFeedService.createAlertFeed({
285
+ await AlertFeedService.createAlertFeedItem({
293
286
  alertId: createdItem.id!,
294
287
  projectId: createdItem.projectId!,
295
288
  alertFeedEventType: AlertFeedEventType.RootCause,
@@ -299,7 +292,7 @@ export class Service extends DatabaseService<Model> {
299
292
  ${createdItem.rootCause || "No root cause provided."}`,
300
293
  });
301
294
 
302
- await AlertFeedService.createAlertFeed({
295
+ await AlertFeedService.createAlertFeedItem({
303
296
  alertId: createdItem.id!,
304
297
  projectId: createdItem.projectId!,
305
298
  alertFeedEventType: AlertFeedEventType.RemediationNotes,
@@ -358,6 +351,35 @@ ${createdItem.remediationNotes || "No remediation notes provided."}`,
358
351
  return createdItem;
359
352
  }
360
353
 
354
+ public async getWorkspaceChannelForAlert(data: {
355
+ alertId: ObjectID;
356
+ workspaceType?: WorkspaceType | null;
357
+ }): Promise<Array<NotificationRuleWorkspaceChannel>> {
358
+ const alert: Model | null = await this.findOneById({
359
+ id: data.alertId,
360
+ select: {
361
+ postUpdatesToWorkspaceChannels: true,
362
+ },
363
+ props: {
364
+ isRoot: true,
365
+ },
366
+ });
367
+
368
+ if (!alert) {
369
+ throw new BadDataException("Incident not found.");
370
+ }
371
+
372
+ return (alert.postUpdatesToWorkspaceChannels || []).filter(
373
+ (channel: NotificationRuleWorkspaceChannel) => {
374
+ if (!data.workspaceType) {
375
+ return true;
376
+ }
377
+
378
+ return channel.workspaceType === data.workspaceType;
379
+ },
380
+ );
381
+ }
382
+
361
383
  public async getAlertIdentifiedDate(alertId: ObjectID): Promise<Date> {
362
384
  const timeline: AlertStateTimeline | null =
363
385
  await AlertStateTimelineService.findOneBy({
@@ -652,7 +674,7 @@ ${alertSeverity.name}
652
674
  }
653
675
 
654
676
  if (shouldAddAlertFeed) {
655
- await AlertFeedService.createAlertFeed({
677
+ await AlertFeedService.createAlertFeedItem({
656
678
  alertId: alertId,
657
679
  projectId: onUpdate.updateBy.props.tenantId as ObjectID,
658
680
  alertFeedEventType: AlertFeedEventType.AlertUpdated,
@@ -1053,5 +1075,25 @@ ${alertSeverity.name}
1053
1075
  logger.error(err);
1054
1076
  });
1055
1077
  }
1078
+
1079
+ public async getAlertNumber(data: {
1080
+ alertId: ObjectID;
1081
+ }): Promise<number | null> {
1082
+ const alert: Model | null = await this.findOneById({
1083
+ id: data.alertId,
1084
+ select: {
1085
+ alertNumber: true,
1086
+ },
1087
+ props: {
1088
+ isRoot: true,
1089
+ },
1090
+ });
1091
+
1092
+ if (!alert) {
1093
+ throw new BadDataException("Alert not found.");
1094
+ }
1095
+
1096
+ return alert.alertNumber || null;
1097
+ }
1056
1098
  }
1057
1099
  export default new Service();
@@ -13,7 +13,6 @@ import ObjectID from "../../Types/ObjectID";
13
13
  import PositiveNumber from "../../Types/PositiveNumber";
14
14
  import AlertState from "Common/Models/DatabaseModels/AlertState";
15
15
  import AlertStateTimeline from "Common/Models/DatabaseModels/AlertStateTimeline";
16
- import User from "Common/Models/DatabaseModels/User";
17
16
  import { IsBillingEnabled } from "../EnvironmentConfig";
18
17
  import { JSONObject } from "../../Types/JSON";
19
18
  import AlertInternalNote from "../../Models/DatabaseModels/AlertInternalNote";
@@ -80,22 +79,13 @@ export class Service extends DatabaseService<AlertStateTimeline> {
80
79
  userId = createBy.data.createdByUser.id;
81
80
  }
82
81
 
83
- const user: User | null = await UserService.findOneBy({
84
- query: {
85
- _id: userId?.toString() as string,
86
- },
87
- select: {
88
- _id: true,
89
- name: true,
90
- email: true,
91
- },
92
- props: {
93
- isRoot: true,
94
- },
95
- });
96
-
97
- if (user) {
98
- createBy.data.rootCause = `Alert state created by ${user.name} (${user.email})`;
82
+ if (userId) {
83
+ createBy.data.rootCause = `Alert state created by ${await UserService.getUserMarkdownString(
84
+ {
85
+ userId: userId,
86
+ projectId: createBy.data.projectId || createBy.props.tenantId!,
87
+ },
88
+ )}`;
99
89
  }
100
90
  }
101
91
 
@@ -190,7 +180,7 @@ export class Service extends DatabaseService<AlertStateTimeline> {
190
180
 
191
181
  const stateName: string = alertState?.name || "";
192
182
 
193
- await AlertFeedService.createAlertFeed({
183
+ await AlertFeedService.createAlertFeedItem({
194
184
  alertId: createdItem.alertId!,
195
185
  projectId: createdItem.projectId!,
196
186
  alertFeedEventType: AlertFeedEventType.AlertStateChanged,
@@ -3,12 +3,21 @@ import Color from "../../Types/Color";
3
3
  import OneUptimeDate from "../../Types/Date";
4
4
  import BadDataException from "../../Types/Exception/BadDataException";
5
5
  import ObjectID from "../../Types/ObjectID";
6
+ import WorkspaceMessagePayload from "../../Types/Workspace/WorkspaceMessagePayload";
6
7
  import { IsBillingEnabled } from "../EnvironmentConfig";
7
8
  import logger from "../Utils/Logger";
8
9
  import DatabaseService from "./DatabaseService";
9
10
  import IncidentFeed, {
10
11
  IncidentFeedEventType,
11
12
  } from "Common/Models/DatabaseModels/IncidentFeed";
13
+ import WorkspaceNotificationRuleService, {
14
+ MessageBlocksByWorkspaceType,
15
+ } from "./WorkspaceNotificationRuleService";
16
+ import NotificationRuleEventType from "../../Types/Workspace/NotificationRules/EventType";
17
+ import IncidentService from "./IncidentService";
18
+ import { WorkspaceChannel } from "../Utils/Workspace/WorkspaceBase";
19
+ import WorkspaceUtil from "../Utils/Workspace/Workspace";
20
+ import WorkspaceType from "../../Types/Workspace/WorkspaceType";
12
21
 
13
22
  export class Service extends DatabaseService<IncidentFeed> {
14
23
  public constructor() {
@@ -19,7 +28,7 @@ export class Service extends DatabaseService<IncidentFeed> {
19
28
  }
20
29
  }
21
30
 
22
- public async createIncidentFeed(data: {
31
+ public async createIncidentFeedItem(data: {
23
32
  incidentId: ObjectID;
24
33
  feedInfoInMarkdown: string;
25
34
  incidentFeedEventType: IncidentFeedEventType;
@@ -28,9 +37,17 @@ export class Service extends DatabaseService<IncidentFeed> {
28
37
  displayColor?: Color | undefined;
29
38
  userId?: ObjectID | undefined;
30
39
  postedAt?: Date | undefined;
40
+ // send notifificatin to slack and teams. This is optional
41
+ workspaceNotification?:
42
+ | {
43
+ notifyUserId?: ObjectID | undefined; // this is oneuptime user id.
44
+ sendWorkspaceNotification: boolean;
45
+ appendMessageBlocks?: Array<MessageBlocksByWorkspaceType> | undefined;
46
+ }
47
+ | undefined;
31
48
  }): Promise<void> {
32
49
  try {
33
- logger.debug("IncidentFeedService.createIncidentFeed");
50
+ logger.debug("IncidentFeedService.createIncidentFeedItem");
34
51
  logger.debug(data);
35
52
 
36
53
  const incidentFeed: IncidentFeed = new IncidentFeed();
@@ -82,6 +99,88 @@ export class Service extends DatabaseService<IncidentFeed> {
82
99
 
83
100
  logger.debug("Incident Feed created");
84
101
  logger.debug(createdIncidentFeed);
102
+
103
+ try {
104
+ // send notification to slack and teams
105
+ if (data.workspaceNotification?.sendWorkspaceNotification) {
106
+ let messageBlocksByWorkspaceTypes: Array<MessageBlocksByWorkspaceType> =
107
+ [];
108
+
109
+ // use markdown to create blocks
110
+ messageBlocksByWorkspaceTypes =
111
+ await WorkspaceUtil.getMessageBlocksByMarkdown({
112
+ userId: data.workspaceNotification.notifyUserId,
113
+ markdown: data.feedInfoInMarkdown,
114
+ projectId: data.projectId,
115
+ });
116
+
117
+ if (data.workspaceNotification.appendMessageBlocks) {
118
+ for (const messageBlocksByWorkspaceType of data
119
+ .workspaceNotification.appendMessageBlocks) {
120
+ const workspaceType: WorkspaceType =
121
+ messageBlocksByWorkspaceType.workspaceType;
122
+
123
+ messageBlocksByWorkspaceTypes
124
+ .find(
125
+ (
126
+ messageBlocksByWorkspaceType: MessageBlocksByWorkspaceType,
127
+ ) => {
128
+ return (
129
+ messageBlocksByWorkspaceType.workspaceType ===
130
+ workspaceType
131
+ );
132
+ },
133
+ )
134
+ ?.messageBlocks.push(
135
+ ...messageBlocksByWorkspaceType.messageBlocks,
136
+ );
137
+ }
138
+ }
139
+
140
+ const workspaceNotificationPaylaods: Array<WorkspaceMessagePayload> =
141
+ [];
142
+
143
+ for (const messageBlocksByWorkspaceType of messageBlocksByWorkspaceTypes) {
144
+ const existingChannels: Array<string> =
145
+ await WorkspaceNotificationRuleService.getExistingChannelNamesBasedOnEventType(
146
+ {
147
+ projectId: data.projectId,
148
+ notificationRuleEventType: NotificationRuleEventType.Incident,
149
+ workspaceType: messageBlocksByWorkspaceType.workspaceType,
150
+ },
151
+ );
152
+
153
+ const incidentChannels: Array<WorkspaceChannel> =
154
+ await IncidentService.getWorkspaceChannelForIncident({
155
+ incidentId: data.incidentId,
156
+ workspaceType: messageBlocksByWorkspaceType.workspaceType,
157
+ });
158
+
159
+ const workspaceMessagePayload: WorkspaceMessagePayload = {
160
+ _type: "WorkspaceMessagePayload",
161
+ workspaceType: messageBlocksByWorkspaceType.workspaceType,
162
+ messageBlocks: messageBlocksByWorkspaceType.messageBlocks,
163
+ channelNames: existingChannels,
164
+ channelIds:
165
+ incidentChannels.map((channel: WorkspaceChannel) => {
166
+ return channel.id;
167
+ }) || [],
168
+ };
169
+
170
+ workspaceNotificationPaylaods.push(workspaceMessagePayload);
171
+ }
172
+
173
+ await WorkspaceUtil.postMessageToAllWorkspaceChannelsAsBot({
174
+ projectId: data.projectId,
175
+ messagePayloadsByWorkspace: workspaceNotificationPaylaods,
176
+ });
177
+ }
178
+ } catch (e) {
179
+ logger.error("Error in sending notification to slack and teams");
180
+ logger.error(e);
181
+
182
+ // we dont throw this error as it is not a critical error
183
+ }
85
184
  } catch (e) {
86
185
  logger.error("Error in creating incident feed");
87
186
  logger.error(e);