@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.
- package/Models/DatabaseModels/OnCallDutyPolicySchedule.ts +68 -1
- package/Models/DatabaseModels/OnCallDutyPolicyScheduleLayer.ts +0 -79
- package/Server/API/OnCallDutyPolicyAPI.ts +87 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1743692467814-MigrationName.ts +35 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1743714801105-MigrationName.ts +23 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +4 -0
- package/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.ts +243 -0
- package/Server/Services/OnCallDutyPolicyEscalationRuleService.ts +46 -0
- package/Server/Services/OnCallDutyPolicyEscalationRuleTeamService.ts +237 -0
- package/Server/Services/OnCallDutyPolicyEscalationRuleUserService.ts +210 -0
- package/Server/Services/OnCallDutyPolicyScheduleLayerService.ts +61 -1
- package/Server/Services/OnCallDutyPolicyScheduleLayerUserService.ts +63 -0
- package/Server/Services/OnCallDutyPolicyScheduleService.ts +597 -18
- package/Server/Services/OnCallDutyPolicyService.ts +129 -0
- package/Server/Services/TeamService.ts +36 -0
- package/Server/Services/UserNotificationSettingService.ts +114 -237
- package/Server/Services/UserService.ts +21 -0
- package/Server/Utils/Workspace/Slack/Actions/Alert.ts +2 -2
- package/Server/Utils/Workspace/Slack/Actions/Incident.ts +3 -3
- package/Types/Date.ts +23 -7
- package/Types/Email/EmailTemplateType.ts +6 -0
- package/Types/NotificationSetting/NotificationSettingEventType.ts +7 -0
- package/Types/OnCallDutyPolicy/Layer.ts +104 -20
- package/UI/Components/Alerts/Alert.tsx +6 -5
- package/UI/Components/HeaderAlert/HeaderAlert.tsx +2 -2
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicySchedule.js +70 -1
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicySchedule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyScheduleLayer.js +0 -82
- package/build/dist/Models/DatabaseModels/OnCallDutyPolicyScheduleLayer.js.map +1 -1
- package/build/dist/Server/API/OnCallDutyPolicyAPI.js +44 -0
- package/build/dist/Server/API/OnCallDutyPolicyAPI.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1743692467814-MigrationName.js +18 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1743692467814-MigrationName.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1743714801105-MigrationName.js +14 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1743714801105-MigrationName.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js +4 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/Index.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js +170 -0
- package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleScheduleService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleService.js +40 -0
- package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleTeamService.js +170 -0
- package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleTeamService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleUserService.js +152 -0
- package/build/dist/Server/Services/OnCallDutyPolicyEscalationRuleUserService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyScheduleLayerService.js +39 -0
- package/build/dist/Server/Services/OnCallDutyPolicyScheduleLayerService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyScheduleLayerUserService.js +42 -0
- package/build/dist/Server/Services/OnCallDutyPolicyScheduleLayerUserService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyScheduleService.js +387 -8
- package/build/dist/Server/Services/OnCallDutyPolicyScheduleService.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyService.js +101 -0
- package/build/dist/Server/Services/OnCallDutyPolicyService.js.map +1 -1
- package/build/dist/Server/Services/TeamService.js +27 -0
- package/build/dist/Server/Services/TeamService.js.map +1 -1
- package/build/dist/Server/Services/UserNotificationSettingService.js +35 -202
- package/build/dist/Server/Services/UserNotificationSettingService.js.map +1 -1
- package/build/dist/Server/Services/UserService.js +17 -0
- package/build/dist/Server/Services/UserService.js.map +1 -1
- package/build/dist/Server/Utils/Workspace/Slack/Actions/Alert.js +2 -2
- package/build/dist/Server/Utils/Workspace/Slack/Actions/Incident.js +3 -3
- package/build/dist/Types/Date.js +19 -7
- package/build/dist/Types/Date.js.map +1 -1
- package/build/dist/Types/Email/EmailTemplateType.js +5 -0
- package/build/dist/Types/Email/EmailTemplateType.js.map +1 -1
- package/build/dist/Types/NotificationSetting/NotificationSettingEventType.js +6 -0
- package/build/dist/Types/NotificationSetting/NotificationSettingEventType.js.map +1 -1
- package/build/dist/Types/OnCallDutyPolicy/Layer.js +66 -11
- package/build/dist/Types/OnCallDutyPolicy/Layer.js.map +1 -1
- package/build/dist/UI/Components/Alerts/Alert.js +4 -4
- package/build/dist/UI/Components/Alerts/Alert.js.map +1 -1
- package/build/dist/UI/Components/HeaderAlert/HeaderAlert.js +2 -2
- package/build/dist/UI/Components/HeaderAlert/HeaderAlert.js.map +1 -1
- package/package.json +2 -2
|
@@ -517,6 +517,28 @@ export default class OnCallDutyPolicySchedule extends BaseModel {
|
|
|
517
517
|
})
|
|
518
518
|
public nextUserIdOnRoster?: ObjectID = undefined;
|
|
519
519
|
|
|
520
|
+
@ColumnAccessControl({
|
|
521
|
+
create: [],
|
|
522
|
+
read: [
|
|
523
|
+
Permission.ProjectOwner,
|
|
524
|
+
Permission.ProjectAdmin,
|
|
525
|
+
Permission.ProjectMember,
|
|
526
|
+
Permission.ReadProjectOnCallDutyPolicySchedule,
|
|
527
|
+
],
|
|
528
|
+
update: [],
|
|
529
|
+
})
|
|
530
|
+
@TableColumn({
|
|
531
|
+
type: TableColumnType.Date,
|
|
532
|
+
title: "Roster Handoff At",
|
|
533
|
+
description:
|
|
534
|
+
"When does the roster handoff occur for this schedule for the current user?",
|
|
535
|
+
})
|
|
536
|
+
@Column({
|
|
537
|
+
type: ColumnType.Date,
|
|
538
|
+
nullable: true,
|
|
539
|
+
})
|
|
540
|
+
public rosterHandoffAt?: Date = undefined;
|
|
541
|
+
|
|
520
542
|
@ColumnAccessControl({
|
|
521
543
|
create: [],
|
|
522
544
|
read: [
|
|
@@ -530,11 +552,56 @@ export default class OnCallDutyPolicySchedule extends BaseModel {
|
|
|
530
552
|
@TableColumn({
|
|
531
553
|
type: TableColumnType.Date,
|
|
532
554
|
title: "Roster Next Handoff At",
|
|
533
|
-
description:
|
|
555
|
+
description:
|
|
556
|
+
"When does the next roster handoff occur for this schedule for the next user?",
|
|
534
557
|
})
|
|
535
558
|
@Column({
|
|
536
559
|
type: ColumnType.Date,
|
|
537
560
|
nullable: true,
|
|
538
561
|
})
|
|
539
562
|
public rosterNextHandoffAt?: Date = undefined;
|
|
563
|
+
|
|
564
|
+
@ColumnAccessControl({
|
|
565
|
+
create: [],
|
|
566
|
+
read: [
|
|
567
|
+
Permission.ProjectOwner,
|
|
568
|
+
Permission.ProjectAdmin,
|
|
569
|
+
Permission.ProjectMember,
|
|
570
|
+
Permission.ReadProjectOnCallDutyPolicySchedule,
|
|
571
|
+
],
|
|
572
|
+
update: [],
|
|
573
|
+
})
|
|
574
|
+
@TableColumn({
|
|
575
|
+
type: TableColumnType.Date,
|
|
576
|
+
title: "Roster Next Event Start At",
|
|
577
|
+
description:
|
|
578
|
+
"When does the next event start for this schedule for the next user?",
|
|
579
|
+
})
|
|
580
|
+
@Column({
|
|
581
|
+
type: ColumnType.Date,
|
|
582
|
+
nullable: true,
|
|
583
|
+
})
|
|
584
|
+
public rosterNextStartAt?: Date = undefined;
|
|
585
|
+
|
|
586
|
+
@ColumnAccessControl({
|
|
587
|
+
create: [],
|
|
588
|
+
read: [
|
|
589
|
+
Permission.ProjectOwner,
|
|
590
|
+
Permission.ProjectAdmin,
|
|
591
|
+
Permission.ProjectMember,
|
|
592
|
+
Permission.ReadProjectOnCallDutyPolicySchedule,
|
|
593
|
+
],
|
|
594
|
+
update: [],
|
|
595
|
+
})
|
|
596
|
+
@TableColumn({
|
|
597
|
+
type: TableColumnType.Date,
|
|
598
|
+
title: "Roster Event Start At",
|
|
599
|
+
description:
|
|
600
|
+
"When does the current event start for this schedule for the current user?",
|
|
601
|
+
})
|
|
602
|
+
@Column({
|
|
603
|
+
type: ColumnType.Date,
|
|
604
|
+
nullable: true,
|
|
605
|
+
})
|
|
606
|
+
public rosterStartAt?: Date = undefined;
|
|
540
607
|
}
|
|
@@ -552,83 +552,4 @@ export default class OnCallDutyPolicyScheduleLayer extends BaseModel {
|
|
|
552
552
|
transformer: RestrictionTimes.getDatabaseTransformer(),
|
|
553
553
|
})
|
|
554
554
|
public restrictionTimes?: RestrictionTimes = undefined;
|
|
555
|
-
|
|
556
|
-
@ColumnAccessControl({
|
|
557
|
-
create: [
|
|
558
|
-
Permission.ProjectOwner,
|
|
559
|
-
Permission.ProjectAdmin,
|
|
560
|
-
Permission.ProjectMember,
|
|
561
|
-
Permission.CreateProjectOnCallDutyPolicySchedule,
|
|
562
|
-
],
|
|
563
|
-
read: [
|
|
564
|
-
Permission.ProjectOwner,
|
|
565
|
-
Permission.ProjectAdmin,
|
|
566
|
-
Permission.ProjectMember,
|
|
567
|
-
Permission.ReadProjectOnCallDutyPolicySchedule,
|
|
568
|
-
],
|
|
569
|
-
update: [],
|
|
570
|
-
})
|
|
571
|
-
@TableColumn({
|
|
572
|
-
manyToOneRelationColumn: "nextUserIdOnLayer",
|
|
573
|
-
type: TableColumnType.Entity,
|
|
574
|
-
modelType: User,
|
|
575
|
-
title: "Next User On Layer",
|
|
576
|
-
description: "Relation to User who is next on layer",
|
|
577
|
-
})
|
|
578
|
-
@ManyToOne(
|
|
579
|
-
() => {
|
|
580
|
-
return User;
|
|
581
|
-
},
|
|
582
|
-
{
|
|
583
|
-
eager: false,
|
|
584
|
-
nullable: true,
|
|
585
|
-
onDelete: "SET NULL",
|
|
586
|
-
orphanedRowAction: "nullify",
|
|
587
|
-
},
|
|
588
|
-
)
|
|
589
|
-
@JoinColumn({ name: "nextUserIdOnLayer" })
|
|
590
|
-
public nextUserOnLayer?: User = undefined;
|
|
591
|
-
|
|
592
|
-
@ColumnAccessControl({
|
|
593
|
-
create: [],
|
|
594
|
-
read: [
|
|
595
|
-
Permission.ProjectOwner,
|
|
596
|
-
Permission.ProjectAdmin,
|
|
597
|
-
Permission.ProjectMember,
|
|
598
|
-
Permission.ReadProjectOnCallDutyPolicySchedule,
|
|
599
|
-
],
|
|
600
|
-
update: [],
|
|
601
|
-
})
|
|
602
|
-
@TableColumn({
|
|
603
|
-
type: TableColumnType.ObjectID,
|
|
604
|
-
title: "Next User ID On Layer",
|
|
605
|
-
description: "Next ID who is currently on layer",
|
|
606
|
-
})
|
|
607
|
-
@Column({
|
|
608
|
-
type: ColumnType.ObjectID,
|
|
609
|
-
nullable: true,
|
|
610
|
-
transformer: ObjectID.getDatabaseTransformer(),
|
|
611
|
-
})
|
|
612
|
-
public nextUserIdOnLayer?: ObjectID = undefined;
|
|
613
|
-
|
|
614
|
-
@ColumnAccessControl({
|
|
615
|
-
create: [],
|
|
616
|
-
read: [
|
|
617
|
-
Permission.ProjectOwner,
|
|
618
|
-
Permission.ProjectAdmin,
|
|
619
|
-
Permission.ProjectMember,
|
|
620
|
-
Permission.ReadProjectOnCallDutyPolicySchedule,
|
|
621
|
-
],
|
|
622
|
-
update: [],
|
|
623
|
-
})
|
|
624
|
-
@TableColumn({
|
|
625
|
-
type: TableColumnType.Date,
|
|
626
|
-
title: "Layer Next Handoff At",
|
|
627
|
-
description: "When is the next layer handoff for this schedule?",
|
|
628
|
-
})
|
|
629
|
-
@Column({
|
|
630
|
-
type: ColumnType.Date,
|
|
631
|
-
nullable: true,
|
|
632
|
-
})
|
|
633
|
-
public layerNextHandoffAt?: Date = undefined;
|
|
634
555
|
}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import UserMiddleware from "../Middleware/UserAuthorization";
|
|
2
|
+
import OnCallDutyPolicyService, {
|
|
3
|
+
Service as OnCallDutyPolicyServiceType,
|
|
4
|
+
} from "../Services/OnCallDutyPolicyService";
|
|
5
|
+
import {
|
|
6
|
+
ExpressRequest,
|
|
7
|
+
ExpressResponse,
|
|
8
|
+
NextFunction,
|
|
9
|
+
} from "../Utils/Express";
|
|
10
|
+
import Response from "../Utils/Response";
|
|
11
|
+
import BaseAPI from "./BaseAPI";
|
|
12
|
+
import CommonAPI from "./CommonAPI";
|
|
13
|
+
import DatabaseCommonInteractionProps from "Common/Types/BaseDatabase/DatabaseCommonInteractionProps";
|
|
14
|
+
import BadDataException from "Common/Types/Exception/BadDataException";
|
|
15
|
+
import ObjectID from "Common/Types/ObjectID";
|
|
16
|
+
import OnCallDutyPolicy from "Common/Models/DatabaseModels/OnCallDutyPolicy";
|
|
17
|
+
import OnCallDutyPolicyEscalationRuleUser from "../../Models/DatabaseModels/OnCallDutyPolicyEscalationRuleUser";
|
|
18
|
+
import OnCallDutyPolicyEscalationRuleTeam from "../../Models/DatabaseModels/OnCallDutyPolicyEscalationRuleTeam";
|
|
19
|
+
import OnCallDutyPolicyEscalationRuleSchedule from "../../Models/DatabaseModels/OnCallDutyPolicyEscalationRuleSchedule";
|
|
20
|
+
import BaseModel from "Common/Models/DatabaseModels/DatabaseBaseModel/DatabaseBaseModel";
|
|
21
|
+
|
|
22
|
+
export default class OnCallDutyPolicyAPI extends BaseAPI<
|
|
23
|
+
OnCallDutyPolicy,
|
|
24
|
+
OnCallDutyPolicyServiceType
|
|
25
|
+
> {
|
|
26
|
+
public constructor() {
|
|
27
|
+
super(OnCallDutyPolicy, OnCallDutyPolicyService);
|
|
28
|
+
|
|
29
|
+
// CNAME verification api. THis API will be used from the dashboard to validate the CNAME MANUALLY.
|
|
30
|
+
this.router.get(
|
|
31
|
+
`${new this.entityType().getCrudApiPath()?.toString()}/current-on-duty-escalation-policies`,
|
|
32
|
+
UserMiddleware.getUserMiddleware,
|
|
33
|
+
async (req: ExpressRequest, res: ExpressResponse, next: NextFunction) => {
|
|
34
|
+
try {
|
|
35
|
+
const databaseProps: DatabaseCommonInteractionProps =
|
|
36
|
+
await CommonAPI.getDatabaseCommonInteractionProps(req);
|
|
37
|
+
|
|
38
|
+
const projectId: ObjectID = databaseProps.tenantId as ObjectID;
|
|
39
|
+
|
|
40
|
+
const userId: ObjectID = databaseProps.userId as ObjectID;
|
|
41
|
+
|
|
42
|
+
if (!projectId) {
|
|
43
|
+
return Response.sendErrorResponse(
|
|
44
|
+
req,
|
|
45
|
+
res,
|
|
46
|
+
new BadDataException("Invalid projectId."),
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (!userId) {
|
|
51
|
+
return Response.sendErrorResponse(
|
|
52
|
+
req,
|
|
53
|
+
res,
|
|
54
|
+
new BadDataException("Invalid userId."),
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const result: {
|
|
59
|
+
escalationRulesByUser: Array<OnCallDutyPolicyEscalationRuleUser>;
|
|
60
|
+
escalationRulesByTeam: Array<OnCallDutyPolicyEscalationRuleTeam>;
|
|
61
|
+
escalationRulesBySchedule: Array<OnCallDutyPolicyEscalationRuleSchedule>;
|
|
62
|
+
} = await this.service.getOnCallPoliciesWhereUserIsOnCallDuty({
|
|
63
|
+
projectId: projectId,
|
|
64
|
+
userId: userId,
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
return Response.sendJsonObjectResponse(req, res, {
|
|
68
|
+
escalationRulesByUser: BaseModel.toJSONArray(
|
|
69
|
+
result.escalationRulesByUser,
|
|
70
|
+
OnCallDutyPolicyEscalationRuleUser,
|
|
71
|
+
),
|
|
72
|
+
escalationRulesByTeam: BaseModel.toJSONArray(
|
|
73
|
+
result.escalationRulesByTeam,
|
|
74
|
+
OnCallDutyPolicyEscalationRuleTeam,
|
|
75
|
+
),
|
|
76
|
+
escalationRulesBySchedule: BaseModel.toJSONArray(
|
|
77
|
+
result.escalationRulesBySchedule,
|
|
78
|
+
OnCallDutyPolicyEscalationRuleSchedule,
|
|
79
|
+
),
|
|
80
|
+
});
|
|
81
|
+
} catch (e) {
|
|
82
|
+
next(e);
|
|
83
|
+
}
|
|
84
|
+
},
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { MigrationInterface, QueryRunner } from "typeorm";
|
|
2
|
+
|
|
3
|
+
export class MigrationName1743692467814 implements MigrationInterface {
|
|
4
|
+
public name = "MigrationName1743692467814";
|
|
5
|
+
|
|
6
|
+
public async up(queryRunner: QueryRunner): Promise<void> {
|
|
7
|
+
await queryRunner.query(
|
|
8
|
+
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" DROP CONSTRAINT "FK_815023b155d367f28cc6855b843"`,
|
|
9
|
+
);
|
|
10
|
+
await queryRunner.query(
|
|
11
|
+
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" DROP COLUMN "nextUserIdOnLayer"`,
|
|
12
|
+
);
|
|
13
|
+
await queryRunner.query(
|
|
14
|
+
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" DROP COLUMN "layerNextHandoffAt"`,
|
|
15
|
+
);
|
|
16
|
+
await queryRunner.query(
|
|
17
|
+
`ALTER TABLE "OnCallDutyPolicySchedule" ADD "rosterHandoffAt" TIMESTAMP WITH TIME ZONE`,
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
public async down(queryRunner: QueryRunner): Promise<void> {
|
|
22
|
+
await queryRunner.query(
|
|
23
|
+
`ALTER TABLE "OnCallDutyPolicySchedule" DROP COLUMN "rosterHandoffAt"`,
|
|
24
|
+
);
|
|
25
|
+
await queryRunner.query(
|
|
26
|
+
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ADD "layerNextHandoffAt" TIMESTAMP WITH TIME ZONE`,
|
|
27
|
+
);
|
|
28
|
+
await queryRunner.query(
|
|
29
|
+
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ADD "nextUserIdOnLayer" uuid`,
|
|
30
|
+
);
|
|
31
|
+
await queryRunner.query(
|
|
32
|
+
`ALTER TABLE "OnCallDutyPolicyScheduleLayer" ADD CONSTRAINT "FK_815023b155d367f28cc6855b843" FOREIGN KEY ("nextUserIdOnLayer") REFERENCES "User"("_id") ON DELETE SET NULL ON UPDATE NO ACTION`,
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { MigrationInterface, QueryRunner } from "typeorm";
|
|
2
|
+
|
|
3
|
+
export class MigrationName1743714801105 implements MigrationInterface {
|
|
4
|
+
public name = "MigrationName1743714801105";
|
|
5
|
+
|
|
6
|
+
public async up(queryRunner: QueryRunner): Promise<void> {
|
|
7
|
+
await queryRunner.query(
|
|
8
|
+
`ALTER TABLE "OnCallDutyPolicySchedule" ADD "rosterNextStartAt" TIMESTAMP WITH TIME ZONE`,
|
|
9
|
+
);
|
|
10
|
+
await queryRunner.query(
|
|
11
|
+
`ALTER TABLE "OnCallDutyPolicySchedule" ADD "rosterStartAt" TIMESTAMP WITH TIME ZONE`,
|
|
12
|
+
);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
public async down(queryRunner: QueryRunner): Promise<void> {
|
|
16
|
+
await queryRunner.query(
|
|
17
|
+
`ALTER TABLE "OnCallDutyPolicySchedule" DROP COLUMN "rosterStartAt"`,
|
|
18
|
+
);
|
|
19
|
+
await queryRunner.query(
|
|
20
|
+
`ALTER TABLE "OnCallDutyPolicySchedule" DROP COLUMN "rosterNextStartAt"`,
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
@@ -127,6 +127,8 @@ import { MigrationName1743518485566 } from "./1743518485566-MigrationName";
|
|
|
127
127
|
import { MigrationName1743521461137 } from "./1743521461137-MigrationName";
|
|
128
128
|
import { MigrationName1743530326936 } from "./1743530326936-MigrationName";
|
|
129
129
|
import { MigrationName1743538648415 } from "./1743538648415-MigrationName";
|
|
130
|
+
import { MigrationName1743692467814 } from "./1743692467814-MigrationName";
|
|
131
|
+
import { MigrationName1743714801105 } from "./1743714801105-MigrationName";
|
|
130
132
|
|
|
131
133
|
export default [
|
|
132
134
|
InitialMigration,
|
|
@@ -258,4 +260,6 @@ export default [
|
|
|
258
260
|
MigrationName1743521461137,
|
|
259
261
|
MigrationName1743530326936,
|
|
260
262
|
MigrationName1743538648415,
|
|
263
|
+
MigrationName1743692467814,
|
|
264
|
+
MigrationName1743714801105,
|
|
261
265
|
];
|
|
@@ -1,10 +1,253 @@
|
|
|
1
|
+
import BadDataException from "../../Types/Exception/BadDataException";
|
|
2
|
+
import ObjectID from "../../Types/ObjectID";
|
|
3
|
+
import { OnCreate, OnDelete } from "../Types/Database/Hooks";
|
|
1
4
|
import DatabaseService from "./DatabaseService";
|
|
2
5
|
import Model from "Common/Models/DatabaseModels/OnCallDutyPolicyEscalationRuleSchedule";
|
|
6
|
+
import Dictionary from "../../Types/Dictionary";
|
|
7
|
+
import OnCallDutyPolicyService from "./OnCallDutyPolicyService";
|
|
8
|
+
import EmailTemplateType from "../../Types/Email/EmailTemplateType";
|
|
9
|
+
import { EmailEnvelope } from "../../Types/Email/EmailMessage";
|
|
10
|
+
import { SMSMessage } from "../../Types/SMS/SMS";
|
|
11
|
+
import UserNotificationSettingService from "./UserNotificationSettingService";
|
|
12
|
+
import NotificationSettingEventType from "../../Types/NotificationSetting/NotificationSettingEventType";
|
|
13
|
+
import { CallRequestMessage } from "../../Types/Call/CallRequest";
|
|
14
|
+
import DeleteBy from "../Types/Database/DeleteBy";
|
|
15
|
+
import { LIMIT_PER_PROJECT } from "../../Types/Database/LimitMax";
|
|
16
|
+
import OnCallDutyPolicyScheduleService from "./OnCallDutyPolicyScheduleService";
|
|
3
17
|
|
|
4
18
|
export class Service extends DatabaseService<Model> {
|
|
5
19
|
public constructor() {
|
|
6
20
|
super(Model);
|
|
7
21
|
}
|
|
22
|
+
|
|
23
|
+
protected override async onCreateSuccess(
|
|
24
|
+
_onCreate: OnCreate<Model>,
|
|
25
|
+
createdItem: Model,
|
|
26
|
+
): Promise<Model> {
|
|
27
|
+
const createdItemId: ObjectID = createdItem.id!;
|
|
28
|
+
|
|
29
|
+
if (!createdItemId) {
|
|
30
|
+
throw new BadDataException("Created item does not have an ID");
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const createdModel: Model | null = await this.findOneById({
|
|
34
|
+
id: createdItemId,
|
|
35
|
+
select: {
|
|
36
|
+
projectId: true,
|
|
37
|
+
onCallDutyPolicyScheduleId: true,
|
|
38
|
+
onCallDutyPolicySchedule: {
|
|
39
|
+
name: true,
|
|
40
|
+
},
|
|
41
|
+
onCallDutyPolicyEscalationRule: {
|
|
42
|
+
name: true,
|
|
43
|
+
_id: true,
|
|
44
|
+
order: true,
|
|
45
|
+
},
|
|
46
|
+
onCallDutyPolicy: {
|
|
47
|
+
name: true,
|
|
48
|
+
_id: true,
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
props: {
|
|
52
|
+
isRoot: true,
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
if (!createdModel) {
|
|
57
|
+
throw new BadDataException("Created item does not have an ID");
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (!createdModel.onCallDutyPolicyScheduleId) {
|
|
61
|
+
throw new BadDataException(
|
|
62
|
+
"Created item does not have a onCallDutyPolicyScheduleId",
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// send notification to the new current user.
|
|
67
|
+
|
|
68
|
+
const userOnSchedule: ObjectID | null =
|
|
69
|
+
await OnCallDutyPolicyScheduleService.getCurrentUserIdInSchedule(
|
|
70
|
+
createdModel.onCallDutyPolicyScheduleId,
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
if (!userOnSchedule) {
|
|
74
|
+
return createdItem;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const scheduleName: string =
|
|
78
|
+
createdModel.onCallDutyPolicySchedule?.name || "No name provided";
|
|
79
|
+
|
|
80
|
+
const sendEmailToUserId: ObjectID | undefined | null = userOnSchedule;
|
|
81
|
+
|
|
82
|
+
if (!sendEmailToUserId) {
|
|
83
|
+
return createdItem;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
if (!createdModel) {
|
|
87
|
+
return createdItem;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const vars: Dictionary<string> = {
|
|
91
|
+
onCallPolicyName:
|
|
92
|
+
createdModel.onCallDutyPolicy?.name || "No name provided",
|
|
93
|
+
escalationRuleName:
|
|
94
|
+
createdModel.onCallDutyPolicyEscalationRule?.name || "No name provided",
|
|
95
|
+
escalationRuleOrder:
|
|
96
|
+
createdModel.onCallDutyPolicyEscalationRule?.order?.toString() ||
|
|
97
|
+
"No order provided",
|
|
98
|
+
reason: "You are currently on roster for schedule " + scheduleName,
|
|
99
|
+
onCallPolicyViewLink: (
|
|
100
|
+
await OnCallDutyPolicyService.getOnCallPolicyLinkInDashboard(
|
|
101
|
+
createdModel!.projectId!,
|
|
102
|
+
createdModel.onCallDutyPolicy!.id!,
|
|
103
|
+
)
|
|
104
|
+
).toString(),
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
// Notify the current user about being added to the schedule.
|
|
108
|
+
const emailMessage: EmailEnvelope = {
|
|
109
|
+
templateType: EmailTemplateType.UserAddedToOnCallPolicy,
|
|
110
|
+
vars: vars,
|
|
111
|
+
subject: `You have been added to the on-call duty policy ${createdModel.onCallDutyPolicy?.name} for schedule ${scheduleName}`,
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
const sms: SMSMessage = {
|
|
115
|
+
message: `This is a message from OneUptime. You have been added to the on-call duty policy ${createdModel.onCallDutyPolicy?.name} for schedule ${scheduleName} and escalation rule ${createdModel.onCallDutyPolicyEscalationRule?.name} with order ${createdModel.onCallDutyPolicyEscalationRule?.order}. To unsubscribe from this notification, go to User Settings in the OneUptime Dashboard.`,
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
const callMessage: CallRequestMessage = {
|
|
119
|
+
data: [
|
|
120
|
+
{
|
|
121
|
+
sayMessage: `This is a message from OneUptime. You have been added to the on-call duty policy ${createdModel.onCallDutyPolicy?.name} for schedule ${scheduleName} and escalation rule ${createdModel.onCallDutyPolicyEscalationRule?.name} with order ${createdModel.onCallDutyPolicyEscalationRule?.order}. To unsubscribe from this notification, go to User Settings in the OneUptime Dashboard. Goodbye.`,
|
|
122
|
+
},
|
|
123
|
+
],
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
await UserNotificationSettingService.sendUserNotification({
|
|
127
|
+
userId: sendEmailToUserId,
|
|
128
|
+
projectId: createdModel!.projectId!,
|
|
129
|
+
emailEnvelope: emailMessage,
|
|
130
|
+
smsMessage: sms,
|
|
131
|
+
callRequestMessage: callMessage,
|
|
132
|
+
eventType:
|
|
133
|
+
NotificationSettingEventType.SEND_WHEN_USER_IS_ADDED_TO_ON_CALL_POLICY,
|
|
134
|
+
});
|
|
135
|
+
|
|
136
|
+
return createdItem;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
protected override async onBeforeDelete(
|
|
140
|
+
deleteBy: DeleteBy<Model>,
|
|
141
|
+
): Promise<OnDelete<Model>> {
|
|
142
|
+
const itemsToFetchBeforeDelete: Array<Model> = await this.findBy({
|
|
143
|
+
query: deleteBy.query,
|
|
144
|
+
props: {
|
|
145
|
+
isRoot: true,
|
|
146
|
+
},
|
|
147
|
+
select: {
|
|
148
|
+
projectId: true,
|
|
149
|
+
onCallDutyPolicyScheduleId: true,
|
|
150
|
+
onCallDutyPolicySchedule: {
|
|
151
|
+
name: true,
|
|
152
|
+
_id: true,
|
|
153
|
+
},
|
|
154
|
+
onCallDutyPolicyEscalationRule: {
|
|
155
|
+
name: true,
|
|
156
|
+
_id: true,
|
|
157
|
+
order: true,
|
|
158
|
+
},
|
|
159
|
+
onCallDutyPolicy: {
|
|
160
|
+
name: true,
|
|
161
|
+
_id: true,
|
|
162
|
+
},
|
|
163
|
+
},
|
|
164
|
+
limit: LIMIT_PER_PROJECT,
|
|
165
|
+
skip: 0,
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
return {
|
|
169
|
+
deleteBy,
|
|
170
|
+
carryForward: {
|
|
171
|
+
deletedItems: itemsToFetchBeforeDelete,
|
|
172
|
+
},
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
protected override async onDeleteSuccess(
|
|
177
|
+
onDelete: OnDelete<Model>,
|
|
178
|
+
_itemIdsBeforeDelete: Array<ObjectID>,
|
|
179
|
+
): Promise<OnDelete<Model>> {
|
|
180
|
+
const deletedItems: Array<Model> = onDelete.carryForward.deletedItems;
|
|
181
|
+
|
|
182
|
+
for (const deletedItem of deletedItems) {
|
|
183
|
+
const userOnSchedule: ObjectID | null =
|
|
184
|
+
await OnCallDutyPolicyScheduleService.getCurrentUserIdInSchedule(
|
|
185
|
+
deletedItem.onCallDutyPolicyScheduleId!,
|
|
186
|
+
);
|
|
187
|
+
|
|
188
|
+
if (!userOnSchedule) {
|
|
189
|
+
continue;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
const sendEmailToUserId: ObjectID | undefined | null = userOnSchedule;
|
|
193
|
+
|
|
194
|
+
if (!sendEmailToUserId) {
|
|
195
|
+
return onDelete;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
const scheduleName: string =
|
|
199
|
+
deletedItem.onCallDutyPolicySchedule?.name || "No name provided";
|
|
200
|
+
|
|
201
|
+
const vars: Dictionary<string> = {
|
|
202
|
+
onCallPolicyName:
|
|
203
|
+
deletedItem.onCallDutyPolicy?.name || "No name provided",
|
|
204
|
+
escalationRuleName:
|
|
205
|
+
deletedItem.onCallDutyPolicyEscalationRule?.name ||
|
|
206
|
+
"No name provided",
|
|
207
|
+
escalationRuleOrder:
|
|
208
|
+
deletedItem.onCallDutyPolicyEscalationRule?.order?.toString() ||
|
|
209
|
+
"No order provided",
|
|
210
|
+
reason: `You have been removed from the on-call duty policy escalation rule for schedule ${scheduleName}.`,
|
|
211
|
+
onCallPolicyViewLink: (
|
|
212
|
+
await OnCallDutyPolicyService.getOnCallPolicyLinkInDashboard(
|
|
213
|
+
deletedItem!.projectId!,
|
|
214
|
+
deletedItem.onCallDutyPolicy!.id!,
|
|
215
|
+
)
|
|
216
|
+
).toString(),
|
|
217
|
+
};
|
|
218
|
+
|
|
219
|
+
// Notify the current user about being removed from the schedule.
|
|
220
|
+
const emailMessage: EmailEnvelope = {
|
|
221
|
+
templateType: EmailTemplateType.UserRemovedFromOnCallPolicy,
|
|
222
|
+
vars: vars,
|
|
223
|
+
subject: `You have been removed from the on-call duty policy ${deletedItem.onCallDutyPolicy?.name} for schedule ${scheduleName}`,
|
|
224
|
+
};
|
|
225
|
+
|
|
226
|
+
const sms: SMSMessage = {
|
|
227
|
+
message: `This is a message from OneUptime. You have been removed from the on-call duty policy ${deletedItem.onCallDutyPolicy?.name} for schedule ${scheduleName} and escalation rule ${deletedItem.onCallDutyPolicyEscalationRule?.name} with order ${deletedItem.onCallDutyPolicyEscalationRule?.order}. To unsubscribe from this notification go to User Settings in OneUptime Dashboard.`,
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
const callMessage: CallRequestMessage = {
|
|
231
|
+
data: [
|
|
232
|
+
{
|
|
233
|
+
sayMessage: `This is a message from OneUptime. You have been removed from the on-call duty policy ${deletedItem.onCallDutyPolicy?.name} for schedule ${scheduleName} and escalation rule ${deletedItem.onCallDutyPolicyEscalationRule?.name} with order ${deletedItem.onCallDutyPolicyEscalationRule?.order}. To unsubscribe from this notification go to User Settings in OneUptime Dashboard. Good Bye`,
|
|
234
|
+
},
|
|
235
|
+
],
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
await UserNotificationSettingService.sendUserNotification({
|
|
239
|
+
userId: sendEmailToUserId,
|
|
240
|
+
projectId: deletedItem!.projectId!,
|
|
241
|
+
emailEnvelope: emailMessage,
|
|
242
|
+
smsMessage: sms,
|
|
243
|
+
callRequestMessage: callMessage,
|
|
244
|
+
eventType:
|
|
245
|
+
NotificationSettingEventType.SEND_WHEN_USER_IS_REMOVED_FROM_ON_CALL_POLICY,
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
return onDelete;
|
|
250
|
+
}
|
|
8
251
|
}
|
|
9
252
|
|
|
10
253
|
export default new Service();
|
|
@@ -671,6 +671,52 @@ export class Service extends DatabaseService<Model> {
|
|
|
671
671
|
select: {
|
|
672
672
|
order: true,
|
|
673
673
|
onCallDutyPolicyId: true,
|
|
674
|
+
projectId: true,
|
|
675
|
+
},
|
|
676
|
+
});
|
|
677
|
+
|
|
678
|
+
if (!resource) {
|
|
679
|
+
throw new BadDataException(
|
|
680
|
+
"OnCallDutyPolicyEscalationRule with this id not found",
|
|
681
|
+
);
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
// delete users in escalation rule, teams in escalation rule and schedules in escalation rule.
|
|
685
|
+
await OnCallDutyPolicyEscalationRuleScheduleService.deleteBy({
|
|
686
|
+
query: {
|
|
687
|
+
onCallDutyPolicyEscalationRuleId: resource.id!,
|
|
688
|
+
projectId: resource.projectId!,
|
|
689
|
+
},
|
|
690
|
+
limit: LIMIT_PER_PROJECT,
|
|
691
|
+
skip: 0,
|
|
692
|
+
props: {
|
|
693
|
+
isRoot: true,
|
|
694
|
+
},
|
|
695
|
+
});
|
|
696
|
+
|
|
697
|
+
// delete users in escalation rule.
|
|
698
|
+
await OnCallDutyPolicyEscalationRuleUserService.deleteBy({
|
|
699
|
+
query: {
|
|
700
|
+
onCallDutyPolicyEscalationRuleId: resource.id!,
|
|
701
|
+
projectId: resource.projectId!,
|
|
702
|
+
},
|
|
703
|
+
limit: LIMIT_PER_PROJECT,
|
|
704
|
+
skip: 0,
|
|
705
|
+
props: {
|
|
706
|
+
isRoot: true,
|
|
707
|
+
},
|
|
708
|
+
});
|
|
709
|
+
|
|
710
|
+
// delete teams in escalation rule.
|
|
711
|
+
await OnCallDutyPolicyEscalationRuleTeamService.deleteBy({
|
|
712
|
+
query: {
|
|
713
|
+
onCallDutyPolicyEscalationRuleId: resource.id!,
|
|
714
|
+
projectId: resource.projectId!,
|
|
715
|
+
},
|
|
716
|
+
limit: LIMIT_PER_PROJECT,
|
|
717
|
+
skip: 0,
|
|
718
|
+
props: {
|
|
719
|
+
isRoot: true,
|
|
674
720
|
},
|
|
675
721
|
});
|
|
676
722
|
}
|