@oneuptime/common 7.0.4006 → 7.0.4019

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 (74) hide show
  1. package/Models/DatabaseModels/OnCallDutyPolicySchedule.ts +68 -1
  2. package/Models/DatabaseModels/OnCallDutyPolicyScheduleLayer.ts +0 -79
  3. package/Server/API/OnCallDutyPolicyAPI.ts +87 -0
  4. package/Server/Infrastructure/Postgres/SchemaMigrations/1743692467814-MigrationName.ts +35 -0
  5. package/Server/Infrastructure/Postgres/SchemaMigrations/1743714801105-MigrationName.ts +23 -0
  6. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +4 -0
  7. package/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.ts +243 -0
  8. package/Server/Services/OnCallDutyPolicyEscalationRuleService.ts +46 -0
  9. package/Server/Services/OnCallDutyPolicyEscalationRuleTeamService.ts +237 -0
  10. package/Server/Services/OnCallDutyPolicyEscalationRuleUserService.ts +210 -0
  11. package/Server/Services/OnCallDutyPolicyScheduleLayerService.ts +61 -1
  12. package/Server/Services/OnCallDutyPolicyScheduleLayerUserService.ts +63 -0
  13. package/Server/Services/OnCallDutyPolicyScheduleService.ts +597 -18
  14. package/Server/Services/OnCallDutyPolicyService.ts +129 -0
  15. package/Server/Services/TeamService.ts +36 -0
  16. package/Server/Services/UserNotificationSettingService.ts +114 -237
  17. package/Server/Services/UserService.ts +21 -0
  18. package/Server/Utils/Workspace/Slack/Actions/Alert.ts +2 -2
  19. package/Server/Utils/Workspace/Slack/Actions/Incident.ts +3 -3
  20. package/Types/Date.ts +23 -7
  21. package/Types/Email/EmailTemplateType.ts +6 -0
  22. package/Types/NotificationSetting/NotificationSettingEventType.ts +7 -0
  23. package/Types/OnCallDutyPolicy/Layer.ts +104 -20
  24. package/UI/Components/Alerts/Alert.tsx +6 -5
  25. package/UI/Components/HeaderAlert/HeaderAlert.tsx +2 -2
  26. package/build/dist/Models/DatabaseModels/OnCallDutyPolicySchedule.js +70 -1
  27. package/build/dist/Models/DatabaseModels/OnCallDutyPolicySchedule.js.map +1 -1
  28. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyScheduleLayer.js +0 -82
  29. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyScheduleLayer.js.map +1 -1
  30. package/build/dist/Server/API/OnCallDutyPolicyAPI.js +44 -0
  31. package/build/dist/Server/API/OnCallDutyPolicyAPI.js.map +1 -0
  32. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1743692467814-MigrationName.js +18 -0
  33. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1743692467814-MigrationName.js.map +1 -0
  34. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1743714801105-MigrationName.js +14 -0
  35. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1743714801105-MigrationName.js.map +1 -0
  36. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +4 -0
  37. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  38. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js +170 -0
  39. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js.map +1 -1
  40. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleService.js +40 -0
  41. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleService.js.map +1 -1
  42. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleTeamService.js +170 -0
  43. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleTeamService.js.map +1 -1
  44. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleUserService.js +152 -0
  45. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleUserService.js.map +1 -1
  46. package/build/dist/Server/Services/OnCallDutyPolicyScheduleLayerService.js +39 -0
  47. package/build/dist/Server/Services/OnCallDutyPolicyScheduleLayerService.js.map +1 -1
  48. package/build/dist/Server/Services/OnCallDutyPolicyScheduleLayerUserService.js +42 -0
  49. package/build/dist/Server/Services/OnCallDutyPolicyScheduleLayerUserService.js.map +1 -1
  50. package/build/dist/Server/Services/OnCallDutyPolicyScheduleService.js +387 -8
  51. package/build/dist/Server/Services/OnCallDutyPolicyScheduleService.js.map +1 -1
  52. package/build/dist/Server/Services/OnCallDutyPolicyService.js +101 -0
  53. package/build/dist/Server/Services/OnCallDutyPolicyService.js.map +1 -1
  54. package/build/dist/Server/Services/TeamService.js +27 -0
  55. package/build/dist/Server/Services/TeamService.js.map +1 -1
  56. package/build/dist/Server/Services/UserNotificationSettingService.js +35 -202
  57. package/build/dist/Server/Services/UserNotificationSettingService.js.map +1 -1
  58. package/build/dist/Server/Services/UserService.js +17 -0
  59. package/build/dist/Server/Services/UserService.js.map +1 -1
  60. package/build/dist/Server/Utils/Workspace/Slack/Actions/Alert.js +2 -2
  61. package/build/dist/Server/Utils/Workspace/Slack/Actions/Incident.js +3 -3
  62. package/build/dist/Types/Date.js +19 -7
  63. package/build/dist/Types/Date.js.map +1 -1
  64. package/build/dist/Types/Email/EmailTemplateType.js +5 -0
  65. package/build/dist/Types/Email/EmailTemplateType.js.map +1 -1
  66. package/build/dist/Types/NotificationSetting/NotificationSettingEventType.js +6 -0
  67. package/build/dist/Types/NotificationSetting/NotificationSettingEventType.js.map +1 -1
  68. package/build/dist/Types/OnCallDutyPolicy/Layer.js +66 -11
  69. package/build/dist/Types/OnCallDutyPolicy/Layer.js.map +1 -1
  70. package/build/dist/UI/Components/Alerts/Alert.js +4 -4
  71. package/build/dist/UI/Components/Alerts/Alert.js.map +1 -1
  72. package/build/dist/UI/Components/HeaderAlert/HeaderAlert.js +2 -2
  73. package/build/dist/UI/Components/HeaderAlert/HeaderAlert.js.map +1 -1
  74. package/package.json +2 -2
@@ -9,6 +9,18 @@ import OnCallDutyPolicyExecutionLog from "Common/Models/DatabaseModels/OnCallDut
9
9
  import DatabaseConfig from "../DatabaseConfig";
10
10
  import URL from "../../Types/API/URL";
11
11
  import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
12
+ import OnCallDutyPolicySchedule from "../../Models/DatabaseModels/OnCallDutyPolicySchedule";
13
+ import OnCallDutyPolicyScheduleService from "./OnCallDutyPolicyScheduleService";
14
+ import TeamService from "./TeamService";
15
+ import Team from "../../Models/DatabaseModels/Team";
16
+ import OnCallDutyPolicyEscalationRuleUser from "../../Models/DatabaseModels/OnCallDutyPolicyEscalationRuleUser";
17
+ import OnCallDutyPolicyEscalationRuleUserService from "./OnCallDutyPolicyEscalationRuleUserService";
18
+ import { LIMIT_PER_PROJECT } from "../../Types/Database/LimitMax";
19
+ import OnCallDutyPolicyEscalationRuleTeam from "../../Models/DatabaseModels/OnCallDutyPolicyEscalationRuleTeam";
20
+ import OnCallDutyPolicyEscalationRuleTeamService from "./OnCallDutyPolicyEscalationRuleTeamService";
21
+ import QueryHelper from "../Types/Database/QueryHelper";
22
+ import OnCallDutyPolicyEscalationRuleSchedule from "../../Models/DatabaseModels/OnCallDutyPolicyEscalationRuleSchedule";
23
+ import OnCallDutyPolicyEscalationRuleScheduleService from "./OnCallDutyPolicyEscalationRuleScheduleService";
12
24
 
13
25
  export class Service extends DatabaseService<OnCallDutyPolicy> {
14
26
  public constructor() {
@@ -100,5 +112,122 @@ export class Service extends DatabaseService<OnCallDutyPolicy> {
100
112
  },
101
113
  });
102
114
  }
115
+
116
+ public async getOnCallPoliciesWhereUserIsOnCallDuty(data: {
117
+ projectId: ObjectID;
118
+ userId: ObjectID;
119
+ }): Promise<{
120
+ escalationRulesByUser: Array<OnCallDutyPolicyEscalationRuleUser>;
121
+ escalationRulesByTeam: Array<OnCallDutyPolicyEscalationRuleTeam>;
122
+ escalationRulesBySchedule: Array<OnCallDutyPolicyEscalationRuleSchedule>;
123
+ }> {
124
+ // get all schedules where user is on call duty.
125
+ const onCallSchedules: Array<OnCallDutyPolicySchedule> =
126
+ await OnCallDutyPolicyScheduleService.getOnCallSchedulesWhereUserIsOnCallDuty(
127
+ data,
128
+ );
129
+
130
+ const teams: Array<Team> = await TeamService.getTeamsUserIsAPartOf({
131
+ userId: data.userId,
132
+ projectId: data.projectId,
133
+ });
134
+
135
+ // get escalationPolicies by user, team and schedule.
136
+ const escalationRulesByUser: Array<OnCallDutyPolicyEscalationRuleUser> =
137
+ await OnCallDutyPolicyEscalationRuleUserService.findBy({
138
+ query: {
139
+ userId: data.userId!,
140
+ projectId: data.projectId!,
141
+ },
142
+ select: {
143
+ onCallDutyPolicyEscalationRule: {
144
+ name: true,
145
+ _id: true,
146
+ order: true,
147
+ },
148
+ onCallDutyPolicy: {
149
+ name: true,
150
+ _id: true,
151
+ },
152
+ },
153
+ limit: LIMIT_PER_PROJECT,
154
+ skip: 0,
155
+ props: {
156
+ isRoot: true,
157
+ },
158
+ });
159
+
160
+ // do the same for teams.
161
+ const escalationRulesByTeam: Array<OnCallDutyPolicyEscalationRuleTeam> =
162
+ await OnCallDutyPolicyEscalationRuleTeamService.findBy({
163
+ query: {
164
+ teamId: QueryHelper.any(
165
+ teams.map((team: Team) => {
166
+ return team.id!;
167
+ }),
168
+ ),
169
+ projectId: data.projectId!,
170
+ },
171
+ select: {
172
+ onCallDutyPolicy: {
173
+ name: true,
174
+ _id: true,
175
+ },
176
+ onCallDutyPolicyEscalationRule: {
177
+ name: true,
178
+ _id: true,
179
+ order: true,
180
+ },
181
+ team: {
182
+ name: true,
183
+ _id: true,
184
+ },
185
+ },
186
+ limit: LIMIT_PER_PROJECT,
187
+ skip: 0,
188
+ props: {
189
+ isRoot: true,
190
+ },
191
+ });
192
+
193
+ // do the same for schedules.
194
+ const escalationRulesBySchedule: Array<OnCallDutyPolicyEscalationRuleSchedule> =
195
+ await OnCallDutyPolicyEscalationRuleScheduleService.findBy({
196
+ query: {
197
+ onCallDutyPolicyScheduleId: QueryHelper.any(
198
+ onCallSchedules.map((schedule: OnCallDutyPolicySchedule) => {
199
+ return schedule.id!;
200
+ }),
201
+ ),
202
+ projectId: data.projectId!,
203
+ },
204
+ select: {
205
+ onCallDutyPolicy: {
206
+ name: true,
207
+ _id: true,
208
+ },
209
+ onCallDutyPolicyEscalationRule: {
210
+ name: true,
211
+ _id: true,
212
+ order: true,
213
+ },
214
+ onCallDutyPolicySchedule: {
215
+ name: true,
216
+ _id: true,
217
+ },
218
+ },
219
+ limit: LIMIT_PER_PROJECT,
220
+ skip: 0,
221
+ props: {
222
+ isRoot: true,
223
+ },
224
+ });
225
+
226
+ return {
227
+ escalationRulesByUser: escalationRulesByUser,
228
+ escalationRulesByTeam: escalationRulesByTeam,
229
+ escalationRulesBySchedule: escalationRulesBySchedule,
230
+ };
231
+ }
103
232
  }
104
233
  export default new Service();
@@ -6,12 +6,48 @@ import LIMIT_MAX from "../../Types/Database/LimitMax";
6
6
  import BadDataException from "../../Types/Exception/BadDataException";
7
7
  import Model from "Common/Models/DatabaseModels/Team";
8
8
  import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
9
+ import ObjectID from "../../Types/ObjectID";
10
+ import TeamMember from "../../Models/DatabaseModels/TeamMember";
11
+ import TeamMemberService from "./TeamMemberService";
9
12
 
10
13
  export class Service extends DatabaseService<Model> {
11
14
  public constructor() {
12
15
  super(Model);
13
16
  }
14
17
 
18
+ public async getTeamsUserIsAPartOf(data: {
19
+ userId: ObjectID;
20
+ projectId: ObjectID;
21
+ }): Promise<Array<Model>> {
22
+ const teamMembers: Array<TeamMember> = await TeamMemberService.findBy({
23
+ query: {
24
+ userId: data.userId,
25
+ projectId: data.projectId,
26
+ },
27
+ select: {
28
+ team: {
29
+ name: true,
30
+ _id: true,
31
+ },
32
+ },
33
+ limit: LIMIT_MAX,
34
+ skip: 0,
35
+ props: {
36
+ isRoot: true,
37
+ },
38
+ });
39
+
40
+ const teams: Array<Model> = [];
41
+
42
+ for (const teamMember of teamMembers) {
43
+ if (teamMember.team) {
44
+ teams.push(teamMember.team);
45
+ }
46
+ }
47
+
48
+ return teams;
49
+ }
50
+
15
51
  @CaptureSpan()
16
52
  protected override async onBeforeUpdate(
17
53
  updateBy: UpdateBy<Model>,
@@ -197,266 +197,143 @@ export class Service extends DatabaseService<UserNotificationSetting> {
197
197
  userId: ObjectID,
198
198
  projectId: ObjectID,
199
199
  ): Promise<void> {
200
- const probeOwnerAddedNotificationEvent: PositiveNumber = await this.countBy(
201
- {
202
- query: {
203
- userId,
204
- projectId,
205
- eventType:
206
- NotificationSettingEventType.SEND_PROBE_OWNER_ADDED_NOTIFICATION,
207
- },
208
- props: {
209
- isRoot: true,
210
- },
211
- },
200
+ await this.addProbeOwnerNotificationSettings(userId, projectId);
201
+ await this.addIncidentNotificationSettings(userId, projectId);
202
+ await this.addMonitorNotificationSettings(userId, projectId);
203
+ await this.addOnCallNotificationSettings(userId, projectId);
204
+ await this.addAlertNotificationSettings(userId, projectId);
205
+ }
206
+
207
+ private async addProbeOwnerNotificationSettings(
208
+ userId: ObjectID,
209
+ projectId: ObjectID,
210
+ ): Promise<void> {
211
+ await this.addNotificationSettingIfNotExists(
212
+ userId,
213
+ projectId,
214
+ NotificationSettingEventType.SEND_PROBE_OWNER_ADDED_NOTIFICATION,
212
215
  );
213
216
 
214
- if (probeOwnerAddedNotificationEvent.toNumber() === 0) {
215
- const item: UserNotificationSetting = new UserNotificationSetting();
216
- item.userId = userId;
217
- item.projectId = projectId;
218
- item.eventType =
219
- NotificationSettingEventType.SEND_PROBE_OWNER_ADDED_NOTIFICATION;
220
- item.alertByEmail = true;
217
+ await this.addNotificationSettingIfNotExists(
218
+ userId,
219
+ projectId,
220
+ NotificationSettingEventType.SEND_PROBE_STATUS_CHANGED_OWNER_NOTIFICATION,
221
+ );
222
+ }
221
223
 
222
- await this.create({
223
- data: item,
224
- props: {
225
- isRoot: true,
226
- },
227
- });
228
- }
224
+ private async addIncidentNotificationSettings(
225
+ userId: ObjectID,
226
+ projectId: ObjectID,
227
+ ): Promise<void> {
228
+ await this.addNotificationSettingIfNotExists(
229
+ userId,
230
+ projectId,
231
+ NotificationSettingEventType.SEND_INCIDENT_CREATED_OWNER_NOTIFICATION,
232
+ );
229
233
 
230
- const probeStatusChangedNotificationEvent: PositiveNumber =
231
- await this.countBy({
232
- query: {
233
- userId,
234
- projectId,
235
- eventType:
236
- NotificationSettingEventType.SEND_PROBE_STATUS_CHANGED_OWNER_NOTIFICATION,
237
- },
238
- props: {
239
- isRoot: true,
240
- },
241
- });
234
+ await this.addNotificationSettingIfNotExists(
235
+ userId,
236
+ projectId,
237
+ NotificationSettingEventType.SEND_INCIDENT_STATE_CHANGED_OWNER_NOTIFICATION,
238
+ );
239
+ }
242
240
 
243
- if (probeStatusChangedNotificationEvent.toNumber() === 0) {
244
- const item: UserNotificationSetting = new UserNotificationSetting();
245
- item.userId = userId;
246
- item.projectId = projectId;
247
- item.eventType =
248
- NotificationSettingEventType.SEND_PROBE_STATUS_CHANGED_OWNER_NOTIFICATION;
249
- item.alertByEmail = true;
241
+ private async addMonitorNotificationSettings(
242
+ userId: ObjectID,
243
+ projectId: ObjectID,
244
+ ): Promise<void> {
245
+ await this.addNotificationSettingIfNotExists(
246
+ userId,
247
+ projectId,
248
+ NotificationSettingEventType.SEND_MONITOR_STATUS_CHANGED_OWNER_NOTIFICATION,
249
+ );
250
250
 
251
- await this.create({
252
- data: item,
253
- props: {
254
- isRoot: true,
255
- },
256
- });
257
- }
251
+ await this.addNotificationSettingIfNotExists(
252
+ userId,
253
+ projectId,
254
+ NotificationSettingEventType.SEND_MONITOR_NOTIFICATION_WHEN_NO_PROBES_ARE_MONITORING_THE_MONITOR,
255
+ );
258
256
 
259
- const incidentCreatedNotificationEvent: PositiveNumber = await this.countBy(
260
- {
261
- query: {
262
- userId,
263
- projectId,
264
- eventType:
265
- NotificationSettingEventType.SEND_INCIDENT_CREATED_OWNER_NOTIFICATION,
266
- },
267
- props: {
268
- isRoot: true,
269
- },
270
- },
257
+ await this.addNotificationSettingIfNotExists(
258
+ userId,
259
+ projectId,
260
+ NotificationSettingEventType.SEND_MONITOR_NOTIFICATION_WHEN_PORBE_STATUS_CHANGES,
271
261
  );
262
+ }
272
263
 
273
- if (incidentCreatedNotificationEvent.toNumber() === 0) {
274
- const item: UserNotificationSetting = new UserNotificationSetting();
275
- item.userId = userId;
276
- item.projectId = projectId;
277
- item.eventType =
278
- NotificationSettingEventType.SEND_INCIDENT_CREATED_OWNER_NOTIFICATION;
279
- item.alertByEmail = true;
264
+ public async addOnCallNotificationSettings(
265
+ userId: ObjectID,
266
+ projectId: ObjectID,
267
+ ): Promise<void> {
268
+ await this.addNotificationSettingIfNotExists(
269
+ userId,
270
+ projectId,
271
+ NotificationSettingEventType.SEND_WHEN_USER_IS_ON_CALL_ROSTER,
272
+ );
280
273
 
281
- await this.create({
282
- data: item,
283
- props: {
284
- isRoot: true,
285
- },
286
- });
287
- }
274
+ await this.addNotificationSettingIfNotExists(
275
+ userId,
276
+ projectId,
277
+ NotificationSettingEventType.SEND_WHEN_USER_IS_NEXT_ON_CALL_ROSTER,
278
+ );
279
+
280
+ await this.addNotificationSettingIfNotExists(
281
+ userId,
282
+ projectId,
283
+ NotificationSettingEventType.SEND_WHEN_USER_IS_ADDED_TO_ON_CALL_POLICY,
284
+ );
285
+
286
+ await this.addNotificationSettingIfNotExists(
287
+ userId,
288
+ projectId,
289
+ NotificationSettingEventType.SEND_WHEN_USER_IS_REMOVED_FROM_ON_CALL_POLICY,
290
+ );
291
+
292
+ await this.addNotificationSettingIfNotExists(
293
+ userId,
294
+ projectId,
295
+ NotificationSettingEventType.SEND_WHEN_USER_IS_NO_LONGER_ACTIVE_ON_ON_CALL_ROSTER,
296
+ );
297
+ }
298
+
299
+ private async addAlertNotificationSettings(
300
+ userId: ObjectID,
301
+ projectId: ObjectID,
302
+ ): Promise<void> {
303
+ await this.addNotificationSettingIfNotExists(
304
+ userId,
305
+ projectId,
306
+ NotificationSettingEventType.SEND_ALERT_CREATED_OWNER_NOTIFICATION,
307
+ );
288
308
 
289
- const alertCreatedNotificationEvent: PositiveNumber = await this.countBy({
309
+ await this.addNotificationSettingIfNotExists(
310
+ userId,
311
+ projectId,
312
+ NotificationSettingEventType.SEND_ALERT_STATE_CHANGED_OWNER_NOTIFICATION,
313
+ );
314
+ }
315
+
316
+ private async addNotificationSettingIfNotExists(
317
+ userId: ObjectID,
318
+ projectId: ObjectID,
319
+ eventType: NotificationSettingEventType,
320
+ ): Promise<void> {
321
+ const existingNotification: PositiveNumber = await this.countBy({
290
322
  query: {
291
323
  userId,
292
324
  projectId,
293
- eventType:
294
- NotificationSettingEventType.SEND_ALERT_CREATED_OWNER_NOTIFICATION,
325
+ eventType,
295
326
  },
296
327
  props: {
297
328
  isRoot: true,
298
329
  },
299
330
  });
300
331
 
301
- if (alertCreatedNotificationEvent.toNumber() === 0) {
302
- const item: UserNotificationSetting = new UserNotificationSetting();
303
- item.userId = userId;
304
- item.projectId = projectId;
305
- item.eventType =
306
- NotificationSettingEventType.SEND_ALERT_CREATED_OWNER_NOTIFICATION;
307
- item.alertByEmail = true;
308
-
309
- await this.create({
310
- data: item,
311
- props: {
312
- isRoot: true,
313
- },
314
- });
315
- }
316
-
317
- // check monitor state changed notification
318
- const monitorStateChangedNotificationEvent: PositiveNumber =
319
- await this.countBy({
320
- query: {
321
- userId,
322
- projectId,
323
- eventType:
324
- NotificationSettingEventType.SEND_MONITOR_STATUS_CHANGED_OWNER_NOTIFICATION,
325
- },
326
- props: {
327
- isRoot: true,
328
- },
329
- });
330
-
331
- if (monitorStateChangedNotificationEvent.toNumber() === 0) {
332
- const item: UserNotificationSetting = new UserNotificationSetting();
333
- item.userId = userId;
334
- item.projectId = projectId;
335
- item.eventType =
336
- NotificationSettingEventType.SEND_MONITOR_STATUS_CHANGED_OWNER_NOTIFICATION;
337
- item.alertByEmail = true;
338
-
339
- await this.create({
340
- data: item,
341
- props: {
342
- isRoot: true,
343
- },
344
- });
345
- }
346
-
347
- // SEND_MONITOR_NOTIFICATION_WHEN_NO_PROBES_ARE_MONITORING_THE_MONITOR
348
-
349
- const monitorNoProbesNotificationEvent: PositiveNumber = await this.countBy(
350
- {
351
- query: {
352
- userId,
353
- projectId,
354
- eventType:
355
- NotificationSettingEventType.SEND_MONITOR_NOTIFICATION_WHEN_NO_PROBES_ARE_MONITORING_THE_MONITOR,
356
- },
357
- props: {
358
- isRoot: true,
359
- },
360
- },
361
- );
362
-
363
- if (monitorNoProbesNotificationEvent.toNumber() === 0) {
364
- const item: UserNotificationSetting = new UserNotificationSetting();
365
- item.userId = userId;
366
- item.projectId = projectId;
367
- item.eventType =
368
- NotificationSettingEventType.SEND_MONITOR_NOTIFICATION_WHEN_NO_PROBES_ARE_MONITORING_THE_MONITOR;
369
- item.alertByEmail = true;
370
-
371
- await this.create({
372
- data: item,
373
- props: {
374
- isRoot: true,
375
- },
376
- });
377
- }
378
-
379
- // SEND_MONITOR_NOTIFICATION_WHEN_PORBE_STATUS_CHANGES
380
-
381
- const monitorProbeStatusChangedNotificationEvent: PositiveNumber =
382
- await this.countBy({
383
- query: {
384
- userId,
385
- projectId,
386
- eventType:
387
- NotificationSettingEventType.SEND_MONITOR_NOTIFICATION_WHEN_PORBE_STATUS_CHANGES,
388
- },
389
- props: {
390
- isRoot: true,
391
- },
392
- });
393
-
394
- if (monitorProbeStatusChangedNotificationEvent.toNumber() === 0) {
395
- const item: UserNotificationSetting = new UserNotificationSetting();
396
- item.userId = userId;
397
- item.projectId = projectId;
398
- item.eventType =
399
- NotificationSettingEventType.SEND_MONITOR_NOTIFICATION_WHEN_PORBE_STATUS_CHANGES;
400
- item.alertByEmail = true;
401
-
402
- await this.create({
403
- data: item,
404
- props: {
405
- isRoot: true,
406
- },
407
- });
408
- }
409
-
410
- // check incident state changed notification
411
- const incidentStateChangedNotificationEvent: PositiveNumber =
412
- await this.countBy({
413
- query: {
414
- userId,
415
- projectId,
416
- eventType:
417
- NotificationSettingEventType.SEND_INCIDENT_STATE_CHANGED_OWNER_NOTIFICATION,
418
- },
419
- props: {
420
- isRoot: true,
421
- },
422
- });
423
-
424
- if (incidentStateChangedNotificationEvent.toNumber() === 0) {
425
- const item: UserNotificationSetting = new UserNotificationSetting();
426
- item.userId = userId;
427
- item.projectId = projectId;
428
- item.eventType =
429
- NotificationSettingEventType.SEND_INCIDENT_STATE_CHANGED_OWNER_NOTIFICATION;
430
- item.alertByEmail = true;
431
-
432
- await this.create({
433
- data: item,
434
- props: {
435
- isRoot: true,
436
- },
437
- });
438
- }
439
-
440
- // check alert state changed notification
441
- const alertStateChangedNotificationEvent: PositiveNumber =
442
- await this.countBy({
443
- query: {
444
- userId,
445
- projectId,
446
- eventType:
447
- NotificationSettingEventType.SEND_ALERT_STATE_CHANGED_OWNER_NOTIFICATION,
448
- },
449
- props: {
450
- isRoot: true,
451
- },
452
- });
453
-
454
- if (alertStateChangedNotificationEvent.toNumber() === 0) {
332
+ if (existingNotification.toNumber() === 0) {
455
333
  const item: UserNotificationSetting = new UserNotificationSetting();
456
334
  item.userId = userId;
457
335
  item.projectId = projectId;
458
- item.eventType =
459
- NotificationSettingEventType.SEND_ALERT_STATE_CHANGED_OWNER_NOTIFICATION;
336
+ item.eventType = eventType;
460
337
  item.alertByEmail = true;
461
338
 
462
339
  await this.create({
@@ -34,6 +34,7 @@ import UserTwoFactorAuthService from "./UserTwoFactorAuthService";
34
34
  import BadDataException from "../../Types/Exception/BadDataException";
35
35
  import Name from "../../Types/Name";
36
36
  import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
37
+ import Timezone from "../../Types/Timezone";
37
38
 
38
39
  export class Service extends DatabaseService<Model> {
39
40
  public constructor() {
@@ -364,6 +365,26 @@ export class Service extends DatabaseService<Model> {
364
365
  props: props,
365
366
  });
366
367
  }
368
+
369
+ public async getTimezoneForUser(userId: ObjectID): Promise<Timezone | null> {
370
+ const user: Model | null = await this.findOneBy({
371
+ query: {
372
+ _id: userId,
373
+ },
374
+ select: {
375
+ timezone: true,
376
+ },
377
+ props: {
378
+ isRoot: true,
379
+ },
380
+ });
381
+
382
+ if (!user) {
383
+ return null;
384
+ }
385
+
386
+ return user.timezone || null;
387
+ }
367
388
  }
368
389
 
369
390
  export default new Service();
@@ -503,7 +503,7 @@ export default class SlackAlertActions {
503
503
  // send a message to the channel visible to user, that the alert has already been Resolved.
504
504
  const markdwonPayload: WorkspacePayloadMarkdown = {
505
505
  _type: "WorkspacePayloadMarkdown",
506
- text: `@${slackUsername}, unfortunately you cannot execute the on call policy for **[Alert ${alertNumber?.toString()}](${await AlertService.getAlertLinkInDashboard(slackRequest.projectId!, alertId)})**. It has already been resolved.`,
506
+ text: `@${slackUsername}, unfortunately you cannot execute the on-call policy for **[Alert ${alertNumber?.toString()}](${await AlertService.getAlertLinkInDashboard(slackRequest.projectId!, alertId)})**. It has already been resolved.`,
507
507
  };
508
508
 
509
509
  await SlackUtil.sendDirectMessageToUser({
@@ -529,7 +529,7 @@ export default class SlackAlertActions {
529
529
  const onCallPolicyString: string =
530
530
  data.slackRequest.viewValues["onCallPolicy"].toString();
531
531
 
532
- // get the on call policy id.
532
+ // get the on-call policy id.
533
533
  const onCallPolicyId: ObjectID = new ObjectID(onCallPolicyString);
534
534
 
535
535
  await OnCallDutyPolicyService.executePolicy(onCallPolicyId, {
@@ -400,7 +400,7 @@ export default class SlackIncidentActions {
400
400
  blocks.push(monitorStatusDropdown);
401
401
  }
402
402
 
403
- // add on call policy dropdown.
403
+ // add on-call policy dropdown.
404
404
 
405
405
  const onCallPolicies: Array<OnCallDutyPolicy> =
406
406
  await OnCallDutyPolicyService.findBy({
@@ -957,7 +957,7 @@ export default class SlackIncidentActions {
957
957
  // send a message to the channel visible to user, that the incident has already been Resolved.
958
958
  const markdwonPayload: WorkspacePayloadMarkdown = {
959
959
  _type: "WorkspacePayloadMarkdown",
960
- text: `@${slackUsername}, unfortunately you cannot execute the on call policy for **[Incident ${incidentNumber?.toString()}](${await IncidentService.getIncidentLinkInDashboard(slackRequest.projectId!, incidentId)})**. It has already been resolved.`,
960
+ text: `@${slackUsername}, unfortunately you cannot execute the on-call policy for **[Incident ${incidentNumber?.toString()}](${await IncidentService.getIncidentLinkInDashboard(slackRequest.projectId!, incidentId)})**. It has already been resolved.`,
961
961
  };
962
962
 
963
963
  await SlackUtil.sendDirectMessageToUser({
@@ -983,7 +983,7 @@ export default class SlackIncidentActions {
983
983
  const onCallPolicyString: string =
984
984
  data.slackRequest.viewValues["onCallPolicy"].toString();
985
985
 
986
- // get the on call policy id.
986
+ // get the on-call policy id.
987
987
  const onCallPolicyId: ObjectID = new ObjectID(onCallPolicyString);
988
988
 
989
989
  await OnCallDutyPolicyService.executePolicy(onCallPolicyId, {