@oneuptime/common 10.2.1 → 10.2.3
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/Index.ts +6 -0
- package/Models/DatabaseModels/ProjectOidc.ts +705 -0
- package/Models/DatabaseModels/UserNotificationRule.ts +49 -0
- package/Models/DatabaseModels/UserNotificationSetting.ts +17 -0
- package/Models/DatabaseModels/UserOnCallLogTimeline.ts +48 -0
- package/Models/DatabaseModels/UserWebhook.ts +290 -0
- package/Models/DatabaseModels/WebhookLog.ts +992 -0
- package/Server/API/ProjectOIDC.ts +73 -0
- package/Server/API/UserWebhookAPI.ts +159 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1778506655291-AddProjectOIDC.ts +79 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/1778514515756-MigrationName.ts +259 -0
- package/Server/Infrastructure/Postgres/SchemaMigrations/Index.ts +4 -0
- package/Server/Services/Index.ts +2 -0
- package/Server/Services/OnCallDutyPolicyScheduleService.ts +139 -26
- package/Server/Services/ProjectOidcService.ts +10 -0
- package/Server/Services/UserNotificationRuleService.ts +213 -1
- package/Server/Services/UserNotificationSettingService.ts +95 -0
- package/Server/Services/UserWebhookService.ts +208 -0
- package/Server/Services/WebhookLogService.ts +15 -0
- package/Server/Services/WebhookService.ts +126 -0
- package/Types/OnCallDutyPolicy/UserOverrideUtil.ts +155 -0
- package/Types/Permission.ts +54 -0
- package/Types/Webhook/WebhookMessage.ts +8 -0
- package/Types/WebhookStatus.ts +6 -0
- package/UI/Components/Calendar/Calendar.css +257 -0
- package/UI/Components/Calendar/Calendar.tsx +22 -11
- package/build/dist/Models/DatabaseModels/Index.js +6 -0
- package/build/dist/Models/DatabaseModels/Index.js.map +1 -1
- package/build/dist/Models/DatabaseModels/ProjectOidc.js +727 -0
- package/build/dist/Models/DatabaseModels/ProjectOidc.js.map +1 -0
- package/build/dist/Models/DatabaseModels/UserNotificationRule.js +49 -0
- package/build/dist/Models/DatabaseModels/UserNotificationRule.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserNotificationSetting.js +19 -0
- package/build/dist/Models/DatabaseModels/UserNotificationSetting.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserOnCallLogTimeline.js +48 -0
- package/build/dist/Models/DatabaseModels/UserOnCallLogTimeline.js.map +1 -1
- package/build/dist/Models/DatabaseModels/UserWebhook.js +307 -0
- package/build/dist/Models/DatabaseModels/UserWebhook.js.map +1 -0
- package/build/dist/Models/DatabaseModels/WebhookLog.js +1021 -0
- package/build/dist/Models/DatabaseModels/WebhookLog.js.map +1 -0
- package/build/dist/Server/API/ProjectOIDC.js +45 -0
- package/build/dist/Server/API/ProjectOIDC.js.map +1 -0
- package/build/dist/Server/API/UserWebhookAPI.js +99 -0
- package/build/dist/Server/API/UserWebhookAPI.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1778506655291-AddProjectOIDC.js +34 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1778506655291-AddProjectOIDC.js.map +1 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1778514515756-MigrationName.js +94 -0
- package/build/dist/Server/Infrastructure/Postgres/SchemaMigrations/1778514515756-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/Index.js +2 -0
- package/build/dist/Server/Services/Index.js.map +1 -1
- package/build/dist/Server/Services/OnCallDutyPolicyScheduleService.js +106 -17
- package/build/dist/Server/Services/OnCallDutyPolicyScheduleService.js.map +1 -1
- package/build/dist/Server/Services/ProjectOidcService.js +9 -0
- package/build/dist/Server/Services/ProjectOidcService.js.map +1 -0
- package/build/dist/Server/Services/UserNotificationRuleService.js +178 -21
- package/build/dist/Server/Services/UserNotificationRuleService.js.map +1 -1
- package/build/dist/Server/Services/UserNotificationSettingService.js +84 -1
- package/build/dist/Server/Services/UserNotificationSettingService.js.map +1 -1
- package/build/dist/Server/Services/UserWebhookService.js +190 -0
- package/build/dist/Server/Services/UserWebhookService.js.map +1 -0
- package/build/dist/Server/Services/WebhookLogService.js +13 -0
- package/build/dist/Server/Services/WebhookLogService.js.map +1 -0
- package/build/dist/Server/Services/WebhookService.js +92 -0
- package/build/dist/Server/Services/WebhookService.js.map +1 -0
- package/build/dist/Types/OnCallDutyPolicy/UserOverrideUtil.js +86 -0
- package/build/dist/Types/OnCallDutyPolicy/UserOverrideUtil.js.map +1 -0
- package/build/dist/Types/Permission.js +50 -0
- package/build/dist/Types/Permission.js.map +1 -1
- package/build/dist/Types/Webhook/WebhookMessage.js +2 -0
- package/build/dist/Types/Webhook/WebhookMessage.js.map +1 -0
- package/build/dist/Types/WebhookStatus.js +7 -0
- package/build/dist/Types/WebhookStatus.js.map +1 -0
- package/build/dist/UI/Components/Calendar/Calendar.js +12 -10
- package/build/dist/UI/Components/Calendar/Calendar.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,12 +1,18 @@
|
|
|
1
1
|
import DatabaseService from "./DatabaseService";
|
|
2
2
|
import OnCallDutyPolicyScheduleLayerService from "./OnCallDutyPolicyScheduleLayerService";
|
|
3
3
|
import OnCallDutyPolicyScheduleLayerUserService from "./OnCallDutyPolicyScheduleLayerUserService";
|
|
4
|
+
import OnCallDutyPolicyUserOverrideService from "./OnCallDutyPolicyUserOverrideService";
|
|
4
5
|
import SortOrder from "../../Types/BaseDatabase/SortOrder";
|
|
5
6
|
import CalendarEvent from "../../Types/Calendar/CalendarEvent";
|
|
6
7
|
import { LIMIT_PER_PROJECT } from "../../Types/Database/LimitMax";
|
|
7
8
|
import OneUptimeDate from "../../Types/Date";
|
|
8
9
|
import ObjectID from "../../Types/ObjectID";
|
|
9
10
|
import LayerUtil, { LayerProps } from "../../Types/OnCallDutyPolicy/Layer";
|
|
11
|
+
import UserOverrideUtil, {
|
|
12
|
+
UserOverrideRecord,
|
|
13
|
+
} from "../../Types/OnCallDutyPolicy/UserOverrideUtil";
|
|
14
|
+
import OnCallDutyPolicyUserOverride from "../../Models/DatabaseModels/OnCallDutyPolicyUserOverride";
|
|
15
|
+
import QueryHelper from "../Types/Database/QueryHelper";
|
|
10
16
|
import OnCallDutyPolicyScheduleLayer from "../../Models/DatabaseModels/OnCallDutyPolicyScheduleLayer";
|
|
11
17
|
import OnCallDutyPolicyScheduleLayerUser from "../../Models/DatabaseModels/OnCallDutyPolicyScheduleLayerUser";
|
|
12
18
|
import User from "../../Models/DatabaseModels/User";
|
|
@@ -914,9 +920,11 @@ export class Service extends DatabaseService<OnCallDutyPolicySchedule> {
|
|
|
914
920
|
return resultReturn;
|
|
915
921
|
}
|
|
916
922
|
|
|
917
|
-
private async getScheduleLayerProps(data: {
|
|
918
|
-
|
|
919
|
-
|
|
923
|
+
private async getScheduleLayerProps(data: { scheduleId: ObjectID }): Promise<{
|
|
924
|
+
layerProps: Array<LayerProps>;
|
|
925
|
+
projectId: ObjectID | null;
|
|
926
|
+
scheduleUserIds: Array<ObjectID>;
|
|
927
|
+
}> {
|
|
920
928
|
// get schedule layers.
|
|
921
929
|
|
|
922
930
|
const scheduleId: ObjectID = data.scheduleId;
|
|
@@ -968,23 +976,34 @@ export class Service extends DatabaseService<OnCallDutyPolicySchedule> {
|
|
|
968
976
|
});
|
|
969
977
|
|
|
970
978
|
const layerProps: Array<LayerProps> = [];
|
|
979
|
+
const scheduleUserIds: Array<ObjectID> = [];
|
|
980
|
+
const seenUserIds: Set<string> = new Set<string>();
|
|
971
981
|
|
|
972
982
|
for (const layer of layers) {
|
|
983
|
+
const usersForLayer: Array<User> = layerUsers
|
|
984
|
+
.filter((layerUser: OnCallDutyPolicyScheduleLayerUser) => {
|
|
985
|
+
return (
|
|
986
|
+
layerUser.onCallDutyPolicyScheduleLayerId?.toString() ===
|
|
987
|
+
layer.id?.toString()
|
|
988
|
+
);
|
|
989
|
+
})
|
|
990
|
+
.map((layerUser: OnCallDutyPolicyScheduleLayerUser) => {
|
|
991
|
+
return layerUser.user!;
|
|
992
|
+
})
|
|
993
|
+
.filter((user: User) => {
|
|
994
|
+
return Boolean(user);
|
|
995
|
+
});
|
|
996
|
+
|
|
997
|
+
for (const user of usersForLayer) {
|
|
998
|
+
const idStr: string = user.id?.toString() || "";
|
|
999
|
+
if (idStr && !seenUserIds.has(idStr)) {
|
|
1000
|
+
seenUserIds.add(idStr);
|
|
1001
|
+
scheduleUserIds.push(user.id!);
|
|
1002
|
+
}
|
|
1003
|
+
}
|
|
1004
|
+
|
|
973
1005
|
layerProps.push({
|
|
974
|
-
users:
|
|
975
|
-
layerUsers
|
|
976
|
-
.filter((layerUser: OnCallDutyPolicyScheduleLayerUser) => {
|
|
977
|
-
return (
|
|
978
|
-
layerUser.onCallDutyPolicyScheduleLayerId?.toString() ===
|
|
979
|
-
layer.id?.toString()
|
|
980
|
-
);
|
|
981
|
-
})
|
|
982
|
-
.map((layerUser: OnCallDutyPolicyScheduleLayerUser) => {
|
|
983
|
-
return layerUser.user!;
|
|
984
|
-
})
|
|
985
|
-
.filter((user: User) => {
|
|
986
|
-
return Boolean(user);
|
|
987
|
-
}) || [],
|
|
1006
|
+
users: usersForLayer,
|
|
988
1007
|
startDateTimeOfLayer: layer.startsAt!,
|
|
989
1008
|
restrictionTimes: layer.restrictionTimes!,
|
|
990
1009
|
rotation: layer.rotation!,
|
|
@@ -992,7 +1011,65 @@ export class Service extends DatabaseService<OnCallDutyPolicySchedule> {
|
|
|
992
1011
|
});
|
|
993
1012
|
}
|
|
994
1013
|
|
|
995
|
-
|
|
1014
|
+
const projectId: ObjectID | null = layers[0]?.projectId || null;
|
|
1015
|
+
|
|
1016
|
+
return { layerProps, projectId, scheduleUserIds };
|
|
1017
|
+
}
|
|
1018
|
+
|
|
1019
|
+
private async fetchOverridesForSchedule(data: {
|
|
1020
|
+
projectId: ObjectID;
|
|
1021
|
+
scheduleUserIds: Array<ObjectID>;
|
|
1022
|
+
windowStart: Date;
|
|
1023
|
+
windowEnd: Date;
|
|
1024
|
+
}): Promise<Array<UserOverrideRecord>> {
|
|
1025
|
+
if (data.scheduleUserIds.length === 0) {
|
|
1026
|
+
return [];
|
|
1027
|
+
}
|
|
1028
|
+
|
|
1029
|
+
const overrides: Array<OnCallDutyPolicyUserOverride> =
|
|
1030
|
+
await OnCallDutyPolicyUserOverrideService.findBy({
|
|
1031
|
+
query: {
|
|
1032
|
+
projectId: data.projectId,
|
|
1033
|
+
startsAt: QueryHelper.lessThanEqualTo(data.windowEnd),
|
|
1034
|
+
endsAt: QueryHelper.greaterThanEqualTo(data.windowStart),
|
|
1035
|
+
},
|
|
1036
|
+
select: {
|
|
1037
|
+
startsAt: true,
|
|
1038
|
+
endsAt: true,
|
|
1039
|
+
overrideUserId: true,
|
|
1040
|
+
routeAlertsToUserId: true,
|
|
1041
|
+
onCallDutyPolicyId: true,
|
|
1042
|
+
},
|
|
1043
|
+
sort: {
|
|
1044
|
+
startsAt: SortOrder.Ascending,
|
|
1045
|
+
},
|
|
1046
|
+
limit: LIMIT_PER_PROJECT,
|
|
1047
|
+
skip: 0,
|
|
1048
|
+
props: {
|
|
1049
|
+
isRoot: true,
|
|
1050
|
+
},
|
|
1051
|
+
});
|
|
1052
|
+
|
|
1053
|
+
const scheduleUserIdSet: Set<string> = new Set<string>(
|
|
1054
|
+
data.scheduleUserIds.map((id: ObjectID) => {
|
|
1055
|
+
return id.toString();
|
|
1056
|
+
}),
|
|
1057
|
+
);
|
|
1058
|
+
|
|
1059
|
+
return overrides
|
|
1060
|
+
.filter((o: OnCallDutyPolicyUserOverride) => {
|
|
1061
|
+
const overrideUserId: string = o.overrideUserId?.toString() || "";
|
|
1062
|
+
return scheduleUserIdSet.has(overrideUserId);
|
|
1063
|
+
})
|
|
1064
|
+
.map((o: OnCallDutyPolicyUserOverride): UserOverrideRecord => {
|
|
1065
|
+
return {
|
|
1066
|
+
overrideUserId: o.overrideUserId?.toString() || "",
|
|
1067
|
+
routeAlertsToUserId: o.routeAlertsToUserId?.toString() || "",
|
|
1068
|
+
startsAt: o.startsAt!,
|
|
1069
|
+
endsAt: o.endsAt!,
|
|
1070
|
+
onCallDutyPolicyId: o.onCallDutyPolicyId?.toString() || null,
|
|
1071
|
+
};
|
|
1072
|
+
});
|
|
996
1073
|
}
|
|
997
1074
|
|
|
998
1075
|
public async getEventByIndexInSchedule(data: {
|
|
@@ -1006,9 +1083,10 @@ export class Service extends DatabaseService<OnCallDutyPolicySchedule> {
|
|
|
1006
1083
|
} as LogAttributes,
|
|
1007
1084
|
);
|
|
1008
1085
|
|
|
1009
|
-
const layerProps
|
|
1010
|
-
|
|
1011
|
-
|
|
1086
|
+
const { layerProps, projectId, scheduleUserIds } =
|
|
1087
|
+
await this.getScheduleLayerProps({
|
|
1088
|
+
scheduleId: data.scheduleId,
|
|
1089
|
+
});
|
|
1012
1090
|
|
|
1013
1091
|
logger.debug("Layer properties fetched: " + JSON.stringify(layerProps), {
|
|
1014
1092
|
onCallDutyPolicyScheduleId: data.scheduleId.toString(),
|
|
@@ -1042,7 +1120,7 @@ export class Service extends DatabaseService<OnCallDutyPolicySchedule> {
|
|
|
1042
1120
|
onCallDutyPolicyScheduleId: data.scheduleId.toString(),
|
|
1043
1121
|
} as LogAttributes);
|
|
1044
1122
|
|
|
1045
|
-
|
|
1123
|
+
let events: Array<CalendarEvent> = this.layerUtil.getMultiLayerEvents(
|
|
1046
1124
|
{
|
|
1047
1125
|
layers: layerProps,
|
|
1048
1126
|
calendarStartDate: currentStartTime,
|
|
@@ -1053,6 +1131,23 @@ export class Service extends DatabaseService<OnCallDutyPolicySchedule> {
|
|
|
1053
1131
|
},
|
|
1054
1132
|
);
|
|
1055
1133
|
|
|
1134
|
+
if (projectId && events.length > 0) {
|
|
1135
|
+
const overrides: Array<UserOverrideRecord> =
|
|
1136
|
+
await this.fetchOverridesForSchedule({
|
|
1137
|
+
projectId,
|
|
1138
|
+
scheduleUserIds,
|
|
1139
|
+
windowStart: currentStartTime,
|
|
1140
|
+
windowEnd: currentEndTime,
|
|
1141
|
+
});
|
|
1142
|
+
|
|
1143
|
+
if (overrides.length > 0) {
|
|
1144
|
+
events = UserOverrideUtil.applyOverridesToEvents({
|
|
1145
|
+
events,
|
|
1146
|
+
overrides,
|
|
1147
|
+
});
|
|
1148
|
+
}
|
|
1149
|
+
}
|
|
1150
|
+
|
|
1056
1151
|
logger.debug("Events fetched: " + JSON.stringify(events), {
|
|
1057
1152
|
onCallDutyPolicyScheduleId: data.scheduleId.toString(),
|
|
1058
1153
|
} as LogAttributes);
|
|
@@ -1064,9 +1159,10 @@ export class Service extends DatabaseService<OnCallDutyPolicySchedule> {
|
|
|
1064
1159
|
public async getCurrentUserIdInSchedule(
|
|
1065
1160
|
scheduleId: ObjectID,
|
|
1066
1161
|
): Promise<ObjectID | null> {
|
|
1067
|
-
const layerProps
|
|
1068
|
-
|
|
1069
|
-
|
|
1162
|
+
const { layerProps, projectId, scheduleUserIds } =
|
|
1163
|
+
await this.getScheduleLayerProps({
|
|
1164
|
+
scheduleId: scheduleId,
|
|
1165
|
+
});
|
|
1070
1166
|
|
|
1071
1167
|
if (layerProps.length === 0) {
|
|
1072
1168
|
return null;
|
|
@@ -1078,7 +1174,7 @@ export class Service extends DatabaseService<OnCallDutyPolicySchedule> {
|
|
|
1078
1174
|
1,
|
|
1079
1175
|
);
|
|
1080
1176
|
|
|
1081
|
-
|
|
1177
|
+
let events: Array<CalendarEvent> = this.layerUtil.getMultiLayerEvents(
|
|
1082
1178
|
{
|
|
1083
1179
|
layers: layerProps,
|
|
1084
1180
|
calendarStartDate: currentStartTime,
|
|
@@ -1089,6 +1185,23 @@ export class Service extends DatabaseService<OnCallDutyPolicySchedule> {
|
|
|
1089
1185
|
},
|
|
1090
1186
|
);
|
|
1091
1187
|
|
|
1188
|
+
if (projectId && events.length > 0) {
|
|
1189
|
+
const overrides: Array<UserOverrideRecord> =
|
|
1190
|
+
await this.fetchOverridesForSchedule({
|
|
1191
|
+
projectId,
|
|
1192
|
+
scheduleUserIds,
|
|
1193
|
+
windowStart: currentStartTime,
|
|
1194
|
+
windowEnd: currentEndTime,
|
|
1195
|
+
});
|
|
1196
|
+
|
|
1197
|
+
if (overrides.length > 0) {
|
|
1198
|
+
events = UserOverrideUtil.applyOverridesToEvents({
|
|
1199
|
+
events,
|
|
1200
|
+
overrides,
|
|
1201
|
+
});
|
|
1202
|
+
}
|
|
1203
|
+
}
|
|
1204
|
+
|
|
1092
1205
|
const currentEvent: CalendarEvent | null = events[0] || null;
|
|
1093
1206
|
|
|
1094
1207
|
if (!currentEvent) {
|
|
@@ -10,6 +10,7 @@ import MailService from "./MailService";
|
|
|
10
10
|
import ShortLinkService from "./ShortLinkService";
|
|
11
11
|
import SmsService from "./SmsService";
|
|
12
12
|
import TelegramService from "./TelegramService";
|
|
13
|
+
import WebhookService from "./WebhookService";
|
|
13
14
|
import WhatsAppService from "./WhatsAppService";
|
|
14
15
|
import UserEmailService from "./UserEmailService";
|
|
15
16
|
import UserOnCallLogService from "./UserOnCallLogService";
|
|
@@ -28,6 +29,7 @@ import Email from "../../Types/Email";
|
|
|
28
29
|
import EmailMessage from "../../Types/Email/EmailMessage";
|
|
29
30
|
import EmailTemplateType from "../../Types/Email/EmailTemplateType";
|
|
30
31
|
import BadDataException from "../../Types/Exception/BadDataException";
|
|
32
|
+
import { JSONObject } from "../../Types/JSON";
|
|
31
33
|
import NotificationRuleType from "../../Types/NotificationRule/NotificationRuleType";
|
|
32
34
|
import ObjectID from "../../Types/ObjectID";
|
|
33
35
|
import PushDeviceType from "../../Types/PushNotification/PushDeviceType";
|
|
@@ -78,6 +80,7 @@ export interface NotificationMethodDescriptor {
|
|
|
78
80
|
userWhatsAppId?: ObjectID;
|
|
79
81
|
userTelegramId?: ObjectID;
|
|
80
82
|
userPushId?: ObjectID;
|
|
83
|
+
userWebhookId?: ObjectID;
|
|
81
84
|
}
|
|
82
85
|
|
|
83
86
|
export class Service extends DatabaseService<Model> {
|
|
@@ -173,6 +176,11 @@ export class Service extends DatabaseService<Model> {
|
|
|
173
176
|
telegramUserHandle: true,
|
|
174
177
|
isVerified: true,
|
|
175
178
|
},
|
|
179
|
+
userWebhook: {
|
|
180
|
+
webhookUrl: true,
|
|
181
|
+
name: true,
|
|
182
|
+
secret: true,
|
|
183
|
+
},
|
|
176
184
|
userEmail: {
|
|
177
185
|
email: true,
|
|
178
186
|
isVerified: true,
|
|
@@ -1082,6 +1090,202 @@ export class Service extends DatabaseService<Model> {
|
|
|
1082
1090
|
});
|
|
1083
1091
|
}
|
|
1084
1092
|
|
|
1093
|
+
// send webhook.
|
|
1094
|
+
if (notificationRuleItem.userWebhook?.webhookUrl) {
|
|
1095
|
+
const webhookUrl: string = notificationRuleItem.userWebhook.webhookUrl;
|
|
1096
|
+
const webhookSecret: string | undefined =
|
|
1097
|
+
notificationRuleItem.userWebhook.secret;
|
|
1098
|
+
const userWebhookId: ObjectID = notificationRuleItem.userWebhook.id!;
|
|
1099
|
+
|
|
1100
|
+
const dispatchWebhook: (params: {
|
|
1101
|
+
eventType: string;
|
|
1102
|
+
payload: JSONObject;
|
|
1103
|
+
entityId?: ObjectID;
|
|
1104
|
+
entityKind: "alert" | "incident" | "alertEpisode" | "incidentEpisode";
|
|
1105
|
+
}) => Promise<void> = async (params: {
|
|
1106
|
+
eventType: string;
|
|
1107
|
+
payload: JSONObject;
|
|
1108
|
+
entityId?: ObjectID;
|
|
1109
|
+
entityKind: "alert" | "incident" | "alertEpisode" | "incidentEpisode";
|
|
1110
|
+
}): Promise<void> => {
|
|
1111
|
+
logTimelineItem.status = UserNotificationStatus.Sending;
|
|
1112
|
+
logTimelineItem.statusMessage = `Sending webhook to ${webhookUrl}.`;
|
|
1113
|
+
logTimelineItem.userWebhookId = userWebhookId;
|
|
1114
|
+
|
|
1115
|
+
const updatedLog: UserOnCallLogTimeline =
|
|
1116
|
+
await UserOnCallLogTimelineService.create({
|
|
1117
|
+
data: logTimelineItem,
|
|
1118
|
+
props: {
|
|
1119
|
+
isRoot: true,
|
|
1120
|
+
},
|
|
1121
|
+
});
|
|
1122
|
+
|
|
1123
|
+
const callbacksByKind: {
|
|
1124
|
+
alert?: { alertId?: ObjectID };
|
|
1125
|
+
incident?: { incidentId?: ObjectID };
|
|
1126
|
+
} = {};
|
|
1127
|
+
if (params.entityKind === "alert" && params.entityId) {
|
|
1128
|
+
callbacksByKind.alert = { alertId: params.entityId };
|
|
1129
|
+
} else if (params.entityKind === "incident" && params.entityId) {
|
|
1130
|
+
callbacksByKind.incident = { incidentId: params.entityId };
|
|
1131
|
+
}
|
|
1132
|
+
|
|
1133
|
+
WebhookService.sendWebhook(
|
|
1134
|
+
{
|
|
1135
|
+
url: webhookUrl,
|
|
1136
|
+
eventType: params.eventType,
|
|
1137
|
+
payload: params.payload,
|
|
1138
|
+
secret: webhookSecret,
|
|
1139
|
+
},
|
|
1140
|
+
{
|
|
1141
|
+
projectId: options.projectId,
|
|
1142
|
+
userOnCallLogTimelineId: updatedLog.id!,
|
|
1143
|
+
userId: notificationRuleItem.userId!,
|
|
1144
|
+
onCallPolicyId: options.onCallPolicyId,
|
|
1145
|
+
onCallPolicyEscalationRuleId: options.onCallPolicyEscalationRuleId,
|
|
1146
|
+
teamId: options.userBelongsToTeamId,
|
|
1147
|
+
onCallDutyPolicyExecutionLogTimelineId:
|
|
1148
|
+
options.onCallDutyPolicyExecutionLogTimelineId,
|
|
1149
|
+
onCallScheduleId: options.onCallScheduleId,
|
|
1150
|
+
...callbacksByKind.alert,
|
|
1151
|
+
...callbacksByKind.incident,
|
|
1152
|
+
},
|
|
1153
|
+
).catch(async (err: Error) => {
|
|
1154
|
+
await UserOnCallLogTimelineService.updateOneById({
|
|
1155
|
+
id: updatedLog.id!,
|
|
1156
|
+
data: {
|
|
1157
|
+
status: UserNotificationStatus.Error,
|
|
1158
|
+
statusMessage: err.message || "Error sending webhook.",
|
|
1159
|
+
},
|
|
1160
|
+
props: {
|
|
1161
|
+
isRoot: true,
|
|
1162
|
+
},
|
|
1163
|
+
});
|
|
1164
|
+
});
|
|
1165
|
+
};
|
|
1166
|
+
|
|
1167
|
+
if (
|
|
1168
|
+
options.userNotificationEventType ===
|
|
1169
|
+
UserNotificationEventType.AlertCreated &&
|
|
1170
|
+
alert
|
|
1171
|
+
) {
|
|
1172
|
+
await dispatchWebhook({
|
|
1173
|
+
eventType: "on-call.alert.created",
|
|
1174
|
+
entityKind: "alert",
|
|
1175
|
+
entityId: alert.id!,
|
|
1176
|
+
payload: {
|
|
1177
|
+
eventType: "on-call.alert.created",
|
|
1178
|
+
timestamp: new Date().toISOString(),
|
|
1179
|
+
projectId: alert.projectId?.toString() || "",
|
|
1180
|
+
userId: notificationRuleItem.userId!.toString(),
|
|
1181
|
+
alert: {
|
|
1182
|
+
id: alert.id?.toString() || "",
|
|
1183
|
+
title: alert.title || "",
|
|
1184
|
+
description: alert.description || "",
|
|
1185
|
+
alertNumber: alert.alertNumber || null,
|
|
1186
|
+
alertNumberWithPrefix: alert.alertNumberWithPrefix || null,
|
|
1187
|
+
severity: alert.alertSeverity?.name || null,
|
|
1188
|
+
state: alert.currentAlertState?.name || null,
|
|
1189
|
+
},
|
|
1190
|
+
onCallPolicyId: options.onCallPolicyId?.toString() || null,
|
|
1191
|
+
onCallPolicyEscalationRuleId:
|
|
1192
|
+
options.onCallPolicyEscalationRuleId?.toString() || null,
|
|
1193
|
+
},
|
|
1194
|
+
});
|
|
1195
|
+
}
|
|
1196
|
+
|
|
1197
|
+
if (
|
|
1198
|
+
options.userNotificationEventType ===
|
|
1199
|
+
UserNotificationEventType.IncidentCreated &&
|
|
1200
|
+
incident
|
|
1201
|
+
) {
|
|
1202
|
+
await dispatchWebhook({
|
|
1203
|
+
eventType: "on-call.incident.created",
|
|
1204
|
+
entityKind: "incident",
|
|
1205
|
+
entityId: incident.id!,
|
|
1206
|
+
payload: {
|
|
1207
|
+
eventType: "on-call.incident.created",
|
|
1208
|
+
timestamp: new Date().toISOString(),
|
|
1209
|
+
projectId: incident.projectId?.toString() || "",
|
|
1210
|
+
userId: notificationRuleItem.userId!.toString(),
|
|
1211
|
+
incident: {
|
|
1212
|
+
id: incident.id?.toString() || "",
|
|
1213
|
+
title: incident.title || "",
|
|
1214
|
+
description: incident.description || "",
|
|
1215
|
+
incidentNumber: incident.incidentNumber || null,
|
|
1216
|
+
incidentNumberWithPrefix:
|
|
1217
|
+
incident.incidentNumberWithPrefix || null,
|
|
1218
|
+
severity: incident.incidentSeverity?.name || null,
|
|
1219
|
+
state: incident.currentIncidentState?.name || null,
|
|
1220
|
+
},
|
|
1221
|
+
onCallPolicyId: options.onCallPolicyId?.toString() || null,
|
|
1222
|
+
onCallPolicyEscalationRuleId:
|
|
1223
|
+
options.onCallPolicyEscalationRuleId?.toString() || null,
|
|
1224
|
+
},
|
|
1225
|
+
});
|
|
1226
|
+
}
|
|
1227
|
+
|
|
1228
|
+
if (
|
|
1229
|
+
options.userNotificationEventType ===
|
|
1230
|
+
UserNotificationEventType.AlertEpisodeCreated &&
|
|
1231
|
+
alertEpisode
|
|
1232
|
+
) {
|
|
1233
|
+
await dispatchWebhook({
|
|
1234
|
+
eventType: "on-call.alertEpisode.created",
|
|
1235
|
+
entityKind: "alertEpisode",
|
|
1236
|
+
payload: {
|
|
1237
|
+
eventType: "on-call.alertEpisode.created",
|
|
1238
|
+
timestamp: new Date().toISOString(),
|
|
1239
|
+
projectId: alertEpisode.projectId?.toString() || "",
|
|
1240
|
+
userId: notificationRuleItem.userId!.toString(),
|
|
1241
|
+
alertEpisode: {
|
|
1242
|
+
id: alertEpisode.id?.toString() || "",
|
|
1243
|
+
title: alertEpisode.title || "",
|
|
1244
|
+
description: alertEpisode.description || "",
|
|
1245
|
+
episodeNumber: alertEpisode.episodeNumber || null,
|
|
1246
|
+
episodeNumberWithPrefix:
|
|
1247
|
+
alertEpisode.episodeNumberWithPrefix || null,
|
|
1248
|
+
severity: alertEpisode.alertSeverity?.name || null,
|
|
1249
|
+
state: alertEpisode.currentAlertState?.name || null,
|
|
1250
|
+
},
|
|
1251
|
+
onCallPolicyId: options.onCallPolicyId?.toString() || null,
|
|
1252
|
+
onCallPolicyEscalationRuleId:
|
|
1253
|
+
options.onCallPolicyEscalationRuleId?.toString() || null,
|
|
1254
|
+
},
|
|
1255
|
+
});
|
|
1256
|
+
}
|
|
1257
|
+
|
|
1258
|
+
if (
|
|
1259
|
+
options.userNotificationEventType ===
|
|
1260
|
+
UserNotificationEventType.IncidentEpisodeCreated &&
|
|
1261
|
+
incidentEpisode
|
|
1262
|
+
) {
|
|
1263
|
+
await dispatchWebhook({
|
|
1264
|
+
eventType: "on-call.incidentEpisode.created",
|
|
1265
|
+
entityKind: "incidentEpisode",
|
|
1266
|
+
payload: {
|
|
1267
|
+
eventType: "on-call.incidentEpisode.created",
|
|
1268
|
+
timestamp: new Date().toISOString(),
|
|
1269
|
+
projectId: incidentEpisode.projectId?.toString() || "",
|
|
1270
|
+
userId: notificationRuleItem.userId!.toString(),
|
|
1271
|
+
incidentEpisode: {
|
|
1272
|
+
id: incidentEpisode.id?.toString() || "",
|
|
1273
|
+
title: incidentEpisode.title || "",
|
|
1274
|
+
description: incidentEpisode.description || "",
|
|
1275
|
+
episodeNumber: incidentEpisode.episodeNumber || null,
|
|
1276
|
+
episodeNumberWithPrefix:
|
|
1277
|
+
incidentEpisode.episodeNumberWithPrefix || null,
|
|
1278
|
+
severity: incidentEpisode.incidentSeverity?.name || null,
|
|
1279
|
+
state: incidentEpisode.currentIncidentState?.name || null,
|
|
1280
|
+
},
|
|
1281
|
+
onCallPolicyId: options.onCallPolicyId?.toString() || null,
|
|
1282
|
+
onCallPolicyEscalationRuleId:
|
|
1283
|
+
options.onCallPolicyEscalationRuleId?.toString() || null,
|
|
1284
|
+
},
|
|
1285
|
+
});
|
|
1286
|
+
}
|
|
1287
|
+
}
|
|
1288
|
+
|
|
1085
1289
|
// send call.
|
|
1086
1290
|
if (
|
|
1087
1291
|
notificationRuleItem.userCall?.phone &&
|
|
@@ -2631,12 +2835,14 @@ export class Service extends DatabaseService<Model> {
|
|
|
2631
2835
|
!createBy.data.userWhatsAppId &&
|
|
2632
2836
|
!createBy.data.userTelegram &&
|
|
2633
2837
|
!createBy.data.userTelegramId &&
|
|
2838
|
+
!createBy.data.userWebhook &&
|
|
2839
|
+
!createBy.data.userWebhookId &&
|
|
2634
2840
|
!createBy.data.userEmailId &&
|
|
2635
2841
|
!createBy.data.userPushId &&
|
|
2636
2842
|
!createBy.data.userPush
|
|
2637
2843
|
) {
|
|
2638
2844
|
throw new BadDataException(
|
|
2639
|
-
"Call, SMS, WhatsApp, Telegram, Email, or Push notification is required",
|
|
2845
|
+
"Call, SMS, WhatsApp, Telegram, Webhook, Email, or Push notification is required",
|
|
2640
2846
|
);
|
|
2641
2847
|
}
|
|
2642
2848
|
|
|
@@ -2701,6 +2907,9 @@ export class Service extends DatabaseService<Model> {
|
|
|
2701
2907
|
if (descriptor.userTelegramId) {
|
|
2702
2908
|
rule.userTelegramId = descriptor.userTelegramId;
|
|
2703
2909
|
}
|
|
2910
|
+
if (descriptor.userWebhookId) {
|
|
2911
|
+
rule.userWebhookId = descriptor.userWebhookId;
|
|
2912
|
+
}
|
|
2704
2913
|
if (descriptor.userPushId) {
|
|
2705
2914
|
rule.userPushId = descriptor.userPushId;
|
|
2706
2915
|
}
|
|
@@ -2725,6 +2934,9 @@ export class Service extends DatabaseService<Model> {
|
|
|
2725
2934
|
if (descriptor.userTelegramId) {
|
|
2726
2935
|
query["userTelegramId"] = descriptor.userTelegramId;
|
|
2727
2936
|
}
|
|
2937
|
+
if (descriptor.userWebhookId) {
|
|
2938
|
+
query["userWebhookId"] = descriptor.userWebhookId;
|
|
2939
|
+
}
|
|
2728
2940
|
if (descriptor.userPushId) {
|
|
2729
2941
|
query["userPushId"] = descriptor.userPushId;
|
|
2730
2942
|
}
|
|
@@ -12,7 +12,9 @@ import UserEmailService from "./UserEmailService";
|
|
|
12
12
|
import UserSmsService from "./UserSmsService";
|
|
13
13
|
import PushNotificationService from "./PushNotificationService";
|
|
14
14
|
import UserTelegramService from "./UserTelegramService";
|
|
15
|
+
import UserWebhookService from "./UserWebhookService";
|
|
15
16
|
import UserWhatsAppService from "./UserWhatsAppService";
|
|
17
|
+
import WebhookService from "./WebhookService";
|
|
16
18
|
import WhatsAppService from "./WhatsAppService";
|
|
17
19
|
import { CallRequestMessage } from "../../Types/Call/CallRequest";
|
|
18
20
|
import { LIMIT_PER_PROJECT } from "../../Types/Database/LimitMax";
|
|
@@ -29,11 +31,13 @@ import TelegramMessage, {
|
|
|
29
31
|
import WhatsAppMessage, {
|
|
30
32
|
WhatsAppMessagePayload,
|
|
31
33
|
} from "../../Types/WhatsApp/WhatsAppMessage";
|
|
34
|
+
import { JSONObject } from "../../Types/JSON";
|
|
32
35
|
import UserCall from "../../Models/DatabaseModels/UserCall";
|
|
33
36
|
import UserEmail from "../../Models/DatabaseModels/UserEmail";
|
|
34
37
|
import UserNotificationSetting from "../../Models/DatabaseModels/UserNotificationSetting";
|
|
35
38
|
import UserSMS from "../../Models/DatabaseModels/UserSMS";
|
|
36
39
|
import UserTelegram from "../../Models/DatabaseModels/UserTelegram";
|
|
40
|
+
import UserWebhook from "../../Models/DatabaseModels/UserWebhook";
|
|
37
41
|
import UserWhatsApp from "../../Models/DatabaseModels/UserWhatsApp";
|
|
38
42
|
import CaptureSpan from "../Utils/Telemetry/CaptureSpan";
|
|
39
43
|
import { appendRecipientToWhatsAppMessage } from "../Utils/WhatsAppTemplateUtil";
|
|
@@ -89,6 +93,7 @@ export class Service extends DatabaseService<UserNotificationSetting> {
|
|
|
89
93
|
alertByTelegram: true,
|
|
90
94
|
alertByCall: true,
|
|
91
95
|
alertByPush: true,
|
|
96
|
+
alertByWebhook: true,
|
|
92
97
|
},
|
|
93
98
|
props: {
|
|
94
99
|
isRoot: true,
|
|
@@ -425,6 +430,96 @@ export class Service extends DatabaseService<UserNotificationSetting> {
|
|
|
425
430
|
logger.error(err);
|
|
426
431
|
});
|
|
427
432
|
}
|
|
433
|
+
|
|
434
|
+
if (notificationSettings.alertByWebhook) {
|
|
435
|
+
const userWebhooks: Array<UserWebhook> =
|
|
436
|
+
await UserWebhookService.findBy({
|
|
437
|
+
query: {
|
|
438
|
+
userId: data.userId,
|
|
439
|
+
projectId: data.projectId,
|
|
440
|
+
},
|
|
441
|
+
select: {
|
|
442
|
+
webhookUrl: true,
|
|
443
|
+
secret: true,
|
|
444
|
+
name: true,
|
|
445
|
+
},
|
|
446
|
+
limit: LIMIT_PER_PROJECT,
|
|
447
|
+
skip: 0,
|
|
448
|
+
props: {
|
|
449
|
+
isRoot: true,
|
|
450
|
+
},
|
|
451
|
+
});
|
|
452
|
+
|
|
453
|
+
const webhookPayload: JSONObject = {
|
|
454
|
+
eventType: data.eventType,
|
|
455
|
+
timestamp: new Date().toISOString(),
|
|
456
|
+
projectId: data.projectId.toString(),
|
|
457
|
+
userId: data.userId.toString(),
|
|
458
|
+
subject: data.emailEnvelope?.subject || "",
|
|
459
|
+
message: data.smsMessage?.message || "",
|
|
460
|
+
};
|
|
461
|
+
|
|
462
|
+
if (data.incidentId) {
|
|
463
|
+
webhookPayload["incidentId"] = data.incidentId.toString();
|
|
464
|
+
}
|
|
465
|
+
if (data.alertId) {
|
|
466
|
+
webhookPayload["alertId"] = data.alertId.toString();
|
|
467
|
+
}
|
|
468
|
+
if (data.monitorId) {
|
|
469
|
+
webhookPayload["monitorId"] = data.monitorId.toString();
|
|
470
|
+
}
|
|
471
|
+
if (data.scheduledMaintenanceId) {
|
|
472
|
+
webhookPayload["scheduledMaintenanceId"] =
|
|
473
|
+
data.scheduledMaintenanceId.toString();
|
|
474
|
+
}
|
|
475
|
+
if (data.statusPageId) {
|
|
476
|
+
webhookPayload["statusPageId"] = data.statusPageId.toString();
|
|
477
|
+
}
|
|
478
|
+
if (data.statusPageAnnouncementId) {
|
|
479
|
+
webhookPayload["statusPageAnnouncementId"] =
|
|
480
|
+
data.statusPageAnnouncementId.toString();
|
|
481
|
+
}
|
|
482
|
+
if (data.onCallPolicyId) {
|
|
483
|
+
webhookPayload["onCallPolicyId"] = data.onCallPolicyId.toString();
|
|
484
|
+
}
|
|
485
|
+
if (data.onCallPolicyEscalationRuleId) {
|
|
486
|
+
webhookPayload["onCallPolicyEscalationRuleId"] =
|
|
487
|
+
data.onCallPolicyEscalationRuleId.toString();
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
for (const userWebhook of userWebhooks) {
|
|
491
|
+
if (!userWebhook.webhookUrl) {
|
|
492
|
+
continue;
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
WebhookService.sendWebhook(
|
|
496
|
+
{
|
|
497
|
+
url: userWebhook.webhookUrl,
|
|
498
|
+
eventType: data.eventType,
|
|
499
|
+
payload: webhookPayload,
|
|
500
|
+
secret: userWebhook.secret,
|
|
501
|
+
},
|
|
502
|
+
{
|
|
503
|
+
projectId: data.projectId,
|
|
504
|
+
incidentId: data.incidentId,
|
|
505
|
+
alertId: data.alertId,
|
|
506
|
+
monitorId: data.monitorId,
|
|
507
|
+
scheduledMaintenanceId: data.scheduledMaintenanceId,
|
|
508
|
+
statusPageId: data.statusPageId,
|
|
509
|
+
statusPageAnnouncementId: data.statusPageAnnouncementId,
|
|
510
|
+
userId: data.userId,
|
|
511
|
+
teamId: data.teamId,
|
|
512
|
+
onCallPolicyId: data.onCallPolicyId,
|
|
513
|
+
onCallPolicyEscalationRuleId: data.onCallPolicyEscalationRuleId,
|
|
514
|
+
onCallDutyPolicyExecutionLogTimelineId:
|
|
515
|
+
data.onCallDutyPolicyExecutionLogTimelineId,
|
|
516
|
+
onCallScheduleId: data.onCallScheduleId,
|
|
517
|
+
},
|
|
518
|
+
).catch((err: Error) => {
|
|
519
|
+
logger.error(err);
|
|
520
|
+
});
|
|
521
|
+
}
|
|
522
|
+
}
|
|
428
523
|
}
|
|
429
524
|
}
|
|
430
525
|
|