@oneuptime/common 7.0.3526 → 7.0.3538

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 (67) hide show
  1. package/Models/DatabaseModels/AlertFeed.ts +12 -4
  2. package/Models/DatabaseModels/OnCallDutyPolicyExecutionLog.ts +2 -0
  3. package/Models/DatabaseModels/OnCallDutyPolicyExecutionLogTimeline.ts +59 -2
  4. package/Models/DatabaseModels/UserNotificationRule.ts +50 -0
  5. package/Models/DatabaseModels/UserOnCallLog.ts +48 -1
  6. package/Models/DatabaseModels/UserOnCallLogTimeline.ts +49 -2
  7. package/Server/API/UserOnCallLogTimelineAPI.ts +32 -8
  8. package/Server/Infrastructure/Postgres/SchemaMigrations/1737141420441-MigrationName.ts +131 -0
  9. package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +2 -0
  10. package/Server/Services/AlertInternalNoteService.ts +73 -0
  11. package/Server/Services/AlertOwnerTeamService.ts +112 -0
  12. package/Server/Services/AlertOwnerUserService.ts +114 -0
  13. package/Server/Services/AlertService.ts +121 -0
  14. package/Server/Services/AlertStateTimelineService.ts +52 -0
  15. package/Server/Services/OnCallDutyPolicyEscalationRuleService.ts +32 -14
  16. package/Server/Services/OnCallDutyPolicyExecutionLogService.ts +86 -27
  17. package/Server/Services/OnCallDutyPolicyExecutionLogTimelineService.ts +30 -12
  18. package/Server/Services/UserNotificationRuleService.ts +450 -67
  19. package/Server/Services/UserOnCallLogService.ts +61 -18
  20. package/Server/Services/UserOnCallLogTimelineService.ts +25 -11
  21. package/Types/Email/EmailTemplateType.ts +1 -0
  22. package/Types/NotificationRule/NotificationRuleType.ts +1 -1
  23. package/build/dist/Models/DatabaseModels/AlertFeed.js +12 -4
  24. package/build/dist/Models/DatabaseModels/AlertFeed.js.map +1 -1
  25. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyExecutionLog.js +2 -0
  26. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyExecutionLog.js.map +1 -1
  27. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyExecutionLogTimeline.js +60 -2
  28. package/build/dist/Models/DatabaseModels/OnCallDutyPolicyExecutionLogTimeline.js.map +1 -1
  29. package/build/dist/Models/DatabaseModels/UserNotificationRule.js +49 -0
  30. package/build/dist/Models/DatabaseModels/UserNotificationRule.js.map +1 -1
  31. package/build/dist/Models/DatabaseModels/UserOnCallLog.js +48 -1
  32. package/build/dist/Models/DatabaseModels/UserOnCallLog.js.map +1 -1
  33. package/build/dist/Models/DatabaseModels/UserOnCallLogTimeline.js +50 -2
  34. package/build/dist/Models/DatabaseModels/UserOnCallLogTimeline.js.map +1 -1
  35. package/build/dist/Server/API/UserOnCallLogTimelineAPI.js +10 -2
  36. package/build/dist/Server/API/UserOnCallLogTimelineAPI.js.map +1 -1
  37. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1737141420441-MigrationName.js +50 -0
  38. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1737141420441-MigrationName.js.map +1 -0
  39. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +2 -0
  40. package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
  41. package/build/dist/Server/Services/AlertInternalNoteService.js +56 -0
  42. package/build/dist/Server/Services/AlertInternalNoteService.js.map +1 -1
  43. package/build/dist/Server/Services/AlertOwnerTeamService.js +86 -0
  44. package/build/dist/Server/Services/AlertOwnerTeamService.js.map +1 -1
  45. package/build/dist/Server/Services/AlertOwnerUserService.js +89 -0
  46. package/build/dist/Server/Services/AlertOwnerUserService.js.map +1 -1
  47. package/build/dist/Server/Services/AlertService.js +107 -3
  48. package/build/dist/Server/Services/AlertService.js.map +1 -1
  49. package/build/dist/Server/Services/AlertStateTimelineService.js +44 -1
  50. package/build/dist/Server/Services/AlertStateTimelineService.js.map +1 -1
  51. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleService.js +18 -8
  52. package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleService.js.map +1 -1
  53. package/build/dist/Server/Services/OnCallDutyPolicyExecutionLogService.js +70 -24
  54. package/build/dist/Server/Services/OnCallDutyPolicyExecutionLogService.js.map +1 -1
  55. package/build/dist/Server/Services/OnCallDutyPolicyExecutionLogTimelineService.js +26 -11
  56. package/build/dist/Server/Services/OnCallDutyPolicyExecutionLogTimelineService.js.map +1 -1
  57. package/build/dist/Server/Services/UserNotificationRuleService.js +334 -67
  58. package/build/dist/Server/Services/UserNotificationRuleService.js.map +1 -1
  59. package/build/dist/Server/Services/UserOnCallLogService.js +66 -27
  60. package/build/dist/Server/Services/UserOnCallLogService.js.map +1 -1
  61. package/build/dist/Server/Services/UserOnCallLogTimelineService.js +16 -5
  62. package/build/dist/Server/Services/UserOnCallLogTimelineService.js.map +1 -1
  63. package/build/dist/Types/Email/EmailTemplateType.js +1 -0
  64. package/build/dist/Types/Email/EmailTemplateType.js.map +1 -1
  65. package/build/dist/Types/NotificationRule/NotificationRuleType.js +1 -1
  66. package/build/dist/Types/NotificationRule/NotificationRuleType.js.map +1 -1
  67. package/package.json +2 -2
@@ -39,6 +39,10 @@ import UserEmail from "Common/Models/DatabaseModels/UserEmail";
39
39
  import Model from "Common/Models/DatabaseModels/UserNotificationRule";
40
40
  import UserOnCallLog from "Common/Models/DatabaseModels/UserOnCallLog";
41
41
  import UserOnCallLogTimeline from "Common/Models/DatabaseModels/UserOnCallLogTimeline";
42
+ import Alert from "../../Models/DatabaseModels/Alert";
43
+ import AlertService from "./AlertService";
44
+ import AlertSeverity from "../../Models/DatabaseModels/AlertSeverity";
45
+ import AlertSeverityService from "./AlertSeverityService";
42
46
 
43
47
  export class Service extends DatabaseService<Model> {
44
48
  public constructor() {
@@ -50,6 +54,7 @@ export class Service extends DatabaseService<Model> {
50
54
  options: {
51
55
  projectId: ObjectID;
52
56
  triggeredByIncidentId?: ObjectID | undefined;
57
+ triggeredByAlertId?: ObjectID | undefined;
53
58
  userNotificationEventType: UserNotificationEventType;
54
59
  onCallPolicyExecutionLogId?: ObjectID | undefined;
55
60
  onCallPolicyId: ObjectID | undefined;
@@ -164,6 +169,10 @@ export class Service extends DatabaseService<Model> {
164
169
  logTimelineItem.triggeredByIncidentId = options.triggeredByIncidentId;
165
170
  }
166
171
 
172
+ if (options.triggeredByAlertId) {
173
+ logTimelineItem.triggeredByAlertId = options.triggeredByAlertId;
174
+ }
175
+
167
176
  if (options.onCallDutyPolicyExecutionLogTimelineId) {
168
177
  logTimelineItem.onCallDutyPolicyExecutionLogTimelineId =
169
178
  options.onCallDutyPolicyExecutionLogTimelineId;
@@ -172,6 +181,7 @@ export class Service extends DatabaseService<Model> {
172
181
  // add status and status message and save.
173
182
 
174
183
  let incident: Incident | null = null;
184
+ let alert: Alert | null = null;
175
185
 
176
186
  if (
177
187
  options.userNotificationEventType ===
@@ -202,15 +212,89 @@ export class Service extends DatabaseService<Model> {
202
212
  });
203
213
  }
204
214
 
205
- if (!incident) {
206
- throw new BadDataException("Incident not found.");
215
+ if (
216
+ options.userNotificationEventType ===
217
+ UserNotificationEventType.AlertCreated &&
218
+ options.triggeredByAlertId
219
+ ) {
220
+ alert = await AlertService.findOneById({
221
+ id: options.triggeredByAlertId!,
222
+ props: {
223
+ isRoot: true,
224
+ },
225
+ select: {
226
+ _id: true,
227
+ title: true,
228
+ description: true,
229
+ projectId: true,
230
+ project: {
231
+ name: true,
232
+ },
233
+ currentAlertState: {
234
+ name: true,
235
+ },
236
+ alertSeverity: {
237
+ name: true,
238
+ },
239
+ },
240
+ });
241
+ }
242
+
243
+ if (!incident && !alert) {
244
+ throw new BadDataException("Incident or Alert not found.");
207
245
  }
208
246
 
209
247
  if (
210
248
  notificationRuleItem.userEmail?.email &&
211
249
  notificationRuleItem.userEmail?.isVerified
212
250
  ) {
213
- // send email.
251
+ // send email for alert.
252
+
253
+ if (
254
+ options.userNotificationEventType ===
255
+ UserNotificationEventType.AlertCreated &&
256
+ alert
257
+ ) {
258
+ // create an error log.
259
+ logTimelineItem.status = UserNotificationStatus.Sending;
260
+ logTimelineItem.statusMessage = `Sending email to ${notificationRuleItem.userEmail?.email.toString()}`;
261
+ logTimelineItem.userEmailId = notificationRuleItem.userEmail.id!;
262
+
263
+ const updatedLog: UserOnCallLogTimeline =
264
+ await UserOnCallLogTimelineService.create({
265
+ data: logTimelineItem,
266
+ props: {
267
+ isRoot: true,
268
+ },
269
+ });
270
+
271
+ const emailMessage: EmailMessage =
272
+ await this.generateEmailTemplateForAlertCreated(
273
+ notificationRuleItem.userEmail?.email,
274
+ alert,
275
+ updatedLog.id!,
276
+ );
277
+
278
+ // send email.
279
+
280
+ MailService.sendMail(emailMessage, {
281
+ userOnCallLogTimelineId: updatedLog.id!,
282
+ projectId: options.projectId,
283
+ }).catch(async (err: Error) => {
284
+ await UserOnCallLogTimelineService.updateOneById({
285
+ id: updatedLog.id!,
286
+ data: {
287
+ status: UserNotificationStatus.Error,
288
+ statusMessage: err.message || "Error sending email.",
289
+ },
290
+ props: {
291
+ isRoot: true,
292
+ },
293
+ });
294
+ });
295
+ }
296
+
297
+ // send email for incident
214
298
  if (
215
299
  options.userNotificationEventType ===
216
300
  UserNotificationEventType.IncidentCreated &&
@@ -278,7 +362,51 @@ export class Service extends DatabaseService<Model> {
278
362
  notificationRuleItem.userSms?.phone &&
279
363
  notificationRuleItem.userSms?.isVerified
280
364
  ) {
281
- // send sms.
365
+ //send sms for alert
366
+ if (
367
+ options.userNotificationEventType ===
368
+ UserNotificationEventType.AlertCreated &&
369
+ alert
370
+ ) {
371
+ // create an error log.
372
+ logTimelineItem.status = UserNotificationStatus.Sending;
373
+ logTimelineItem.statusMessage = `Sending SMS to ${notificationRuleItem.userSms?.phone.toString()}.`;
374
+ logTimelineItem.userSmsId = notificationRuleItem.userSms.id!;
375
+
376
+ const updatedLog: UserOnCallLogTimeline =
377
+ await UserOnCallLogTimelineService.create({
378
+ data: logTimelineItem,
379
+ props: {
380
+ isRoot: true,
381
+ },
382
+ });
383
+
384
+ const smsMessage: SMS = await this.generateSmsTemplateForAlertCreated(
385
+ notificationRuleItem.userSms.phone,
386
+ alert,
387
+ updatedLog.id!,
388
+ );
389
+
390
+ // send email.
391
+
392
+ SmsService.sendSms(smsMessage, {
393
+ projectId: alert.projectId,
394
+ userOnCallLogTimelineId: updatedLog.id!,
395
+ }).catch(async (err: Error) => {
396
+ await UserOnCallLogTimelineService.updateOneById({
397
+ id: updatedLog.id!,
398
+ data: {
399
+ status: UserNotificationStatus.Error,
400
+ statusMessage: err.message || "Error sending SMS.",
401
+ },
402
+ props: {
403
+ isRoot: true,
404
+ },
405
+ });
406
+ });
407
+ }
408
+
409
+ // send sms for incident
282
410
  if (
283
411
  options.userNotificationEventType ===
284
412
  UserNotificationEventType.IncidentCreated &&
@@ -345,43 +473,94 @@ export class Service extends DatabaseService<Model> {
345
473
  notificationRuleItem.userCall?.phone &&
346
474
  notificationRuleItem.userCall?.isVerified
347
475
  ) {
348
- // send call.
349
- logTimelineItem.status = UserNotificationStatus.Sending;
350
- logTimelineItem.statusMessage = `Making a call to ${notificationRuleItem.userCall?.phone.toString()}.`;
351
- logTimelineItem.userCallId = notificationRuleItem.userCall.id!;
352
-
353
- const updatedLog: UserOnCallLogTimeline =
354
- await UserOnCallLogTimelineService.create({
355
- data: logTimelineItem,
356
- props: {
357
- isRoot: true,
358
- },
476
+ // send call for alert
477
+ if (
478
+ options.userNotificationEventType ===
479
+ UserNotificationEventType.AlertCreated &&
480
+ alert
481
+ ) {
482
+ // create an error log.
483
+ logTimelineItem.status = UserNotificationStatus.Sending;
484
+ logTimelineItem.statusMessage = `Making a call to ${notificationRuleItem.userCall?.phone.toString()}.`;
485
+ logTimelineItem.userCallId = notificationRuleItem.userCall.id!;
486
+
487
+ const updatedLog: UserOnCallLogTimeline =
488
+ await UserOnCallLogTimelineService.create({
489
+ data: logTimelineItem,
490
+ props: {
491
+ isRoot: true,
492
+ },
493
+ });
494
+
495
+ const callRequest: CallRequest =
496
+ await this.generateCallTemplateForAlertCreated(
497
+ notificationRuleItem.userCall?.phone,
498
+ alert,
499
+ updatedLog.id!,
500
+ );
501
+
502
+ // send email.
503
+
504
+ CallService.makeCall(callRequest, {
505
+ projectId: alert.projectId,
506
+ userOnCallLogTimelineId: updatedLog.id!,
507
+ }).catch(async (err: Error) => {
508
+ await UserOnCallLogTimelineService.updateOneById({
509
+ id: updatedLog.id!,
510
+ data: {
511
+ status: UserNotificationStatus.Error,
512
+ statusMessage: err.message || "Error making call.",
513
+ },
514
+ props: {
515
+ isRoot: true,
516
+ },
517
+ });
359
518
  });
519
+ }
360
520
 
361
- const callRequest: CallRequest =
362
- await this.generateCallTemplateForIncidentCreated(
363
- notificationRuleItem.userCall?.phone,
364
- incident,
365
- updatedLog.id!,
366
- );
521
+ if (
522
+ options.userNotificationEventType ===
523
+ UserNotificationEventType.IncidentCreated &&
524
+ incident
525
+ ) {
526
+ // send call for incident
527
+ logTimelineItem.status = UserNotificationStatus.Sending;
528
+ logTimelineItem.statusMessage = `Making a call to ${notificationRuleItem.userCall?.phone.toString()}.`;
529
+ logTimelineItem.userCallId = notificationRuleItem.userCall.id!;
367
530
 
368
- // send email.
369
-
370
- CallService.makeCall(callRequest, {
371
- projectId: incident.projectId,
372
- userOnCallLogTimelineId: updatedLog.id!,
373
- }).catch(async (err: Error) => {
374
- await UserOnCallLogTimelineService.updateOneById({
375
- id: updatedLog.id!,
376
- data: {
377
- status: UserNotificationStatus.Error,
378
- statusMessage: err.message || "Error making call.",
379
- },
380
- props: {
381
- isRoot: true,
382
- },
531
+ const updatedLog: UserOnCallLogTimeline =
532
+ await UserOnCallLogTimelineService.create({
533
+ data: logTimelineItem,
534
+ props: {
535
+ isRoot: true,
536
+ },
537
+ });
538
+
539
+ const callRequest: CallRequest =
540
+ await this.generateCallTemplateForIncidentCreated(
541
+ notificationRuleItem.userCall?.phone,
542
+ incident,
543
+ updatedLog.id!,
544
+ );
545
+
546
+ // send email.
547
+
548
+ CallService.makeCall(callRequest, {
549
+ projectId: incident.projectId,
550
+ userOnCallLogTimelineId: updatedLog.id!,
551
+ }).catch(async (err: Error) => {
552
+ await UserOnCallLogTimelineService.updateOneById({
553
+ id: updatedLog.id!,
554
+ data: {
555
+ status: UserNotificationStatus.Error,
556
+ statusMessage: err.message || "Error making call.",
557
+ },
558
+ props: {
559
+ isRoot: true,
560
+ },
561
+ });
383
562
  });
384
- });
563
+ }
385
564
  }
386
565
 
387
566
  if (
@@ -401,6 +580,56 @@ export class Service extends DatabaseService<Model> {
401
580
  }
402
581
  }
403
582
 
583
+ public async generateCallTemplateForAlertCreated(
584
+ to: Phone,
585
+ alert: Alert,
586
+ userOnCallLogTimelineId: ObjectID,
587
+ ): Promise<CallRequest> {
588
+ const host: Hostname = await DatabaseConfig.getHost();
589
+
590
+ const httpProtocol: Protocol = await DatabaseConfig.getHttpProtocol();
591
+
592
+ const callRequest: CallRequest = {
593
+ to: to,
594
+ data: [
595
+ {
596
+ sayMessage: "This is a call from OneUptime",
597
+ },
598
+ {
599
+ sayMessage: "A new alert has been created",
600
+ },
601
+ {
602
+ sayMessage: alert.title!,
603
+ },
604
+ {
605
+ introMessage: "To acknowledge this alert press 1",
606
+ numDigits: 1,
607
+ timeoutInSeconds: 10,
608
+ noInputMessage: "You have not entered any input. Good bye",
609
+ onInputCallRequest: {
610
+ "1": {
611
+ sayMessage: "You have acknowledged this alert. Good bye",
612
+ },
613
+ default: {
614
+ sayMessage: "Invalid input. Good bye",
615
+ },
616
+ },
617
+ responseUrl: new URL(
618
+ httpProtocol,
619
+ host,
620
+ new Route(AppApiRoute.toString())
621
+ .addRoute(new UserOnCallLogTimeline().crudApiPath!)
622
+ .addRoute(
623
+ "/call/gather-input/" + userOnCallLogTimelineId.toString(),
624
+ ),
625
+ ),
626
+ },
627
+ ],
628
+ };
629
+
630
+ return callRequest;
631
+ }
632
+
404
633
  public async generateCallTemplateForIncidentCreated(
405
634
  to: Phone,
406
635
  incident: Incident,
@@ -451,6 +680,35 @@ export class Service extends DatabaseService<Model> {
451
680
  return callRequest;
452
681
  }
453
682
 
683
+ public async generateSmsTemplateForAlertCreated(
684
+ to: Phone,
685
+ alert: Alert,
686
+ userOnCallLogTimelineId: ObjectID,
687
+ ): Promise<SMS> {
688
+ const host: Hostname = await DatabaseConfig.getHost();
689
+ const httpProtocol: Protocol = await DatabaseConfig.getHttpProtocol();
690
+
691
+ const shortUrl: ShortLink = await ShortLinkService.saveShortLinkFor(
692
+ new URL(
693
+ httpProtocol,
694
+ host,
695
+ new Route(AppApiRoute.toString())
696
+ .addRoute(new UserOnCallLogTimeline().crudApiPath!)
697
+ .addRoute("/acknowledge/" + userOnCallLogTimelineId.toString()),
698
+ ),
699
+ );
700
+ const url: URL = await ShortLinkService.getShortenedUrl(shortUrl);
701
+
702
+ const sms: SMS = {
703
+ to,
704
+ message: `This is a message from OneUptime. A new alert has been created. ${
705
+ alert.title
706
+ }. To acknowledge this alert, please click on the following link ${url.toString()}`,
707
+ };
708
+
709
+ return sms;
710
+ }
711
+
454
712
  public async generateSmsTemplateForIncidentCreated(
455
713
  to: Phone,
456
714
  incident: Incident,
@@ -480,6 +738,45 @@ export class Service extends DatabaseService<Model> {
480
738
  return sms;
481
739
  }
482
740
 
741
+ public async generateEmailTemplateForAlertCreated(
742
+ to: Email,
743
+ alert: Alert,
744
+ userOnCallLogTimelineId: ObjectID,
745
+ ): Promise<EmailMessage> {
746
+ const host: Hostname = await DatabaseConfig.getHost();
747
+ const httpProtocol: Protocol = await DatabaseConfig.getHttpProtocol();
748
+
749
+ const vars: Dictionary<string> = {
750
+ alertTitle: alert.title!,
751
+ projectName: alert.project!.name!,
752
+ currentState: alert.currentAlertState!.name!,
753
+ alertDescription: await Markdown.convertToHTML(
754
+ alert.description! || "",
755
+ MarkdownContentType.Email,
756
+ ),
757
+ alertSeverity: alert.alertSeverity!.name!,
758
+ alertViewLink: (
759
+ await AlertService.getAlertLinkInDashboard(alert.projectId!, alert.id!)
760
+ ).toString(),
761
+ acknowledgeAlertLink: new URL(
762
+ httpProtocol,
763
+ host,
764
+ new Route(AppApiRoute.toString())
765
+ .addRoute(new UserOnCallLogTimeline().crudApiPath!)
766
+ .addRoute("/acknowledge/" + userOnCallLogTimelineId.toString()),
767
+ ).toString(),
768
+ };
769
+
770
+ const emailMessage: EmailMessage = {
771
+ toEmail: to!,
772
+ templateType: EmailTemplateType.AcknowledgeAlert,
773
+ vars: vars,
774
+ subject: "ACTION REQUIRED: Alert created - " + alert.title!,
775
+ };
776
+
777
+ return emailMessage;
778
+ }
779
+
483
780
  public async generateEmailTemplateForIncidentCreated(
484
781
  to: Email,
485
782
  incident: Incident,
@@ -529,6 +826,7 @@ export class Service extends DatabaseService<Model> {
529
826
  options: {
530
827
  projectId: ObjectID;
531
828
  triggeredByIncidentId?: ObjectID | undefined;
829
+ triggeredByAlertId?: ObjectID | undefined;
532
830
  userNotificationEventType: UserNotificationEventType;
533
831
  onCallPolicyExecutionLogId?: ObjectID | undefined;
534
832
  onCallPolicyId: ObjectID | undefined;
@@ -548,6 +846,10 @@ export class Service extends DatabaseService<Model> {
548
846
  userOnCallLog.triggeredByIncidentId = options.triggeredByIncidentId;
549
847
  }
550
848
 
849
+ if (options.triggeredByAlertId) {
850
+ userOnCallLog.triggeredByAlertId = options.triggeredByAlertId;
851
+ }
852
+
551
853
  userOnCallLog.userNotificationEventType = options.userNotificationEventType;
552
854
 
553
855
  if (options.onCallPolicyExecutionLogId) {
@@ -608,11 +910,13 @@ export class Service extends DatabaseService<Model> {
608
910
  };
609
911
  }
610
912
 
611
- public async addDefaultNotificationRuleForUser(
612
- projectId: ObjectID,
613
- userId: ObjectID,
614
- email: Email,
615
- ): Promise<void> {
913
+ public async addDefaultIncidentNotificationRuleForUser(data: {
914
+ projectId: ObjectID;
915
+ userId: ObjectID;
916
+ userEmail: UserEmail;
917
+ }): Promise<void> {
918
+ const { projectId, userId, userEmail } = data;
919
+
616
920
  const incidentSeverities: Array<IncidentSeverity> =
617
921
  await IncidentSeverityService.findBy({
618
922
  query: {
@@ -628,44 +932,76 @@ export class Service extends DatabaseService<Model> {
628
932
  },
629
933
  });
630
934
 
631
- //check userEmail
935
+ // create for incident severities.
936
+ for (const incidentSeverity of incidentSeverities) {
937
+ //check if this rule already exists.
938
+ const existingRule: Model | null = await this.findOneBy({
939
+ query: {
940
+ projectId,
941
+ userId,
942
+ userEmailId: userEmail.id!,
943
+ incidentSeverityId: incidentSeverity.id!,
944
+ ruleType: NotificationRuleType.ON_CALL_EXECUTED,
945
+ },
946
+ props: {
947
+ isRoot: true,
948
+ },
949
+ });
632
950
 
633
- let userEmail: UserEmail | null = await UserEmailService.findOneBy({
634
- query: {
635
- projectId,
636
- userId,
637
- email,
638
- },
639
- props: {
640
- isRoot: true,
641
- },
642
- });
951
+ if (existingRule) {
952
+ continue; // skip this rule.
953
+ }
643
954
 
644
- if (!userEmail) {
645
- userEmail = new UserEmail();
646
- userEmail.projectId = projectId;
647
- userEmail.userId = userId;
648
- userEmail.email = email;
649
- userEmail.isVerified = true;
955
+ const notificationRule: Model = new Model();
650
956
 
651
- userEmail = await UserEmailService.create({
652
- data: userEmail,
957
+ notificationRule.projectId = projectId;
958
+ notificationRule.userId = userId;
959
+ notificationRule.userEmailId = userEmail.id!;
960
+ notificationRule.incidentSeverityId = incidentSeverity.id!;
961
+ notificationRule.notifyAfterMinutes = 0;
962
+ notificationRule.ruleType = NotificationRuleType.ON_CALL_EXECUTED;
963
+
964
+ await this.create({
965
+ data: notificationRule,
653
966
  props: {
654
967
  isRoot: true,
655
968
  },
656
969
  });
657
970
  }
971
+ }
658
972
 
659
- // create for incident severities.
660
- for (const incidentSeverity of incidentSeverities) {
973
+ public async addDefaultAlertNotificationRulesForUser(data: {
974
+ projectId: ObjectID;
975
+ userId: ObjectID;
976
+ userEmail: UserEmail;
977
+ }): Promise<void> {
978
+ const { projectId, userId, userEmail } = data;
979
+
980
+ const alertSeverities: Array<AlertSeverity> =
981
+ await AlertSeverityService.findBy({
982
+ query: {
983
+ projectId,
984
+ },
985
+ props: {
986
+ isRoot: true,
987
+ },
988
+ limit: LIMIT_PER_PROJECT,
989
+ skip: 0,
990
+ select: {
991
+ _id: true,
992
+ },
993
+ });
994
+
995
+ // create for Alert severities.
996
+ for (const alertSeverity of alertSeverities) {
661
997
  //check if this rule already exists.
662
998
  const existingRule: Model | null = await this.findOneBy({
663
999
  query: {
664
1000
  projectId,
665
1001
  userId,
666
1002
  userEmailId: userEmail.id!,
667
- incidentSeverityId: incidentSeverity.id!,
668
- ruleType: NotificationRuleType.ON_CALL_INCIDENT_CREATED,
1003
+ alertSeverityId: alertSeverity.id!,
1004
+ ruleType: NotificationRuleType.ON_CALL_EXECUTED,
669
1005
  },
670
1006
  props: {
671
1007
  isRoot: true,
@@ -681,9 +1017,9 @@ export class Service extends DatabaseService<Model> {
681
1017
  notificationRule.projectId = projectId;
682
1018
  notificationRule.userId = userId;
683
1019
  notificationRule.userEmailId = userEmail.id!;
684
- notificationRule.incidentSeverityId = incidentSeverity.id!;
1020
+ notificationRule.alertSeverityId = alertSeverity.id!;
685
1021
  notificationRule.notifyAfterMinutes = 0;
686
- notificationRule.ruleType = NotificationRuleType.ON_CALL_INCIDENT_CREATED;
1022
+ notificationRule.ruleType = NotificationRuleType.ON_CALL_EXECUTED;
687
1023
 
688
1024
  await this.create({
689
1025
  data: notificationRule,
@@ -692,6 +1028,53 @@ export class Service extends DatabaseService<Model> {
692
1028
  },
693
1029
  });
694
1030
  }
1031
+ }
1032
+
1033
+ public async addDefaultNotificationRuleForUser(
1034
+ projectId: ObjectID,
1035
+ userId: ObjectID,
1036
+ email: Email,
1037
+ ): Promise<void> {
1038
+ let userEmail: UserEmail | null = await UserEmailService.findOneBy({
1039
+ query: {
1040
+ projectId,
1041
+ userId,
1042
+ email,
1043
+ },
1044
+ props: {
1045
+ isRoot: true,
1046
+ },
1047
+ });
1048
+
1049
+ if (!userEmail) {
1050
+ userEmail = new UserEmail();
1051
+ userEmail.projectId = projectId;
1052
+ userEmail.userId = userId;
1053
+ userEmail.email = email;
1054
+ userEmail.isVerified = true;
1055
+
1056
+ userEmail = await UserEmailService.create({
1057
+ data: userEmail,
1058
+ props: {
1059
+ isRoot: true,
1060
+ },
1061
+ });
1062
+ }
1063
+
1064
+ // add default incident rules for user
1065
+ await this.addDefaultIncidentNotificationRuleForUser({
1066
+ projectId,
1067
+ userId,
1068
+ userEmail,
1069
+ });
1070
+
1071
+ // add default alert rules for user, just like the incident
1072
+
1073
+ await this.addDefaultAlertNotificationRulesForUser({
1074
+ projectId,
1075
+ userId,
1076
+ userEmail,
1077
+ });
695
1078
 
696
1079
  //check if this rule already exists.
697
1080
  const existingRuleOnCall: Model | null = await this.findOneBy({