mirror of
https://github.com/OneUptime/oneuptime.git
synced 2026-04-06 00:32:12 +02:00
374 lines
14 KiB
TypeScript
374 lines
14 KiB
TypeScript
import BadDataException from "../../Types/Exception/BadDataException";
|
|
import ObjectID from "../../Types/ObjectID";
|
|
import { OnCreate, OnDelete } from "../Types/Database/Hooks";
|
|
import DatabaseService from "./DatabaseService";
|
|
import Model from "../../Models/DatabaseModels/OnCallDutyPolicyEscalationRuleUser";
|
|
import Dictionary from "../../Types/Dictionary";
|
|
import OnCallDutyPolicyService from "./OnCallDutyPolicyService";
|
|
import EmailTemplateType from "../../Types/Email/EmailTemplateType";
|
|
import { EmailEnvelope } from "../../Types/Email/EmailMessage";
|
|
import { SMSMessage } from "../../Types/SMS/SMS";
|
|
import UserNotificationSettingService from "./UserNotificationSettingService";
|
|
import NotificationSettingEventType from "../../Types/NotificationSetting/NotificationSettingEventType";
|
|
import { CallRequestMessage } from "../../Types/Call/CallRequest";
|
|
import DeleteBy from "../Types/Database/DeleteBy";
|
|
import { LIMIT_PER_PROJECT } from "../../Types/Database/LimitMax";
|
|
import OnCallDutyPolicyFeedService from "./OnCallDutyPolicyFeedService";
|
|
import { OnCallDutyPolicyFeedEventType } from "../../Models/DatabaseModels/OnCallDutyPolicyFeed";
|
|
import { Gray500, Red500 } from "../../Types/BrandColors";
|
|
import UserService from "./UserService";
|
|
import User from "../../Models/DatabaseModels/User";
|
|
import PushNotificationMessage from "../../Types/PushNotification/PushNotificationMessage";
|
|
import PushNotificationUtil from "../Utils/PushNotificationUtil";
|
|
import OnCallDutyPolicyTimeLogService from "./OnCallDutyPolicyTimeLogService";
|
|
import OneUptimeDate from "../../Types/Date";
|
|
import { createWhatsAppMessageFromTemplate } from "../Utils/WhatsAppTemplateUtil";
|
|
import logger from "../Utils/Logger";
|
|
import { WhatsAppMessagePayload } from "../../Types/WhatsApp/WhatsAppMessage";
|
|
|
|
export class Service extends DatabaseService<Model> {
|
|
public constructor() {
|
|
super(Model);
|
|
}
|
|
|
|
protected override async onCreateSuccess(
|
|
_onCreate: OnCreate<Model>,
|
|
createdItem: Model,
|
|
): Promise<Model> {
|
|
const createdItemId: ObjectID = createdItem.id!;
|
|
|
|
if (!createdItemId) {
|
|
throw new BadDataException("Created item does not have an ID");
|
|
}
|
|
|
|
const createdModel: Model | null = await this.findOneById({
|
|
id: createdItemId,
|
|
select: {
|
|
projectId: true,
|
|
user: {
|
|
timezone: true,
|
|
_id: true,
|
|
},
|
|
onCallDutyPolicyEscalationRule: {
|
|
name: true,
|
|
_id: true,
|
|
order: true,
|
|
},
|
|
onCallDutyPolicy: {
|
|
name: true,
|
|
_id: true,
|
|
},
|
|
createdByUserId: true,
|
|
},
|
|
props: {
|
|
isRoot: true,
|
|
},
|
|
});
|
|
|
|
// send notification to the new current user.
|
|
|
|
const sendEmailToUserId: ObjectID | undefined | null =
|
|
createdModel?.user?.id;
|
|
|
|
if (!sendEmailToUserId) {
|
|
return createdItem;
|
|
}
|
|
|
|
if (!createdModel) {
|
|
return createdItem;
|
|
}
|
|
|
|
const vars: Dictionary<string> = {
|
|
onCallPolicyName:
|
|
createdModel.onCallDutyPolicy?.name || "No name provided",
|
|
escalationRuleName:
|
|
createdModel.onCallDutyPolicyEscalationRule?.name || "No name provided",
|
|
escalationRuleOrder:
|
|
createdModel.onCallDutyPolicyEscalationRule?.order?.toString() ||
|
|
"No order provided",
|
|
reason: "You have been added to the on-call duty policy escalation rule.",
|
|
onCallPolicyViewLink: (
|
|
await OnCallDutyPolicyService.getOnCallDutyPolicyLinkInDashboard(
|
|
createdModel!.projectId!,
|
|
createdModel.onCallDutyPolicy!.id!,
|
|
)
|
|
).toString(),
|
|
};
|
|
|
|
// current user changed, send alert the new current user.
|
|
const emailMessage: EmailEnvelope = {
|
|
templateType: EmailTemplateType.UserAddedToOnCallPolicy,
|
|
vars: vars,
|
|
subject: `You have been added to the on-call duty policy ${createdModel.onCallDutyPolicy?.name}`,
|
|
};
|
|
|
|
const sms: SMSMessage = {
|
|
message: `This is a message from OneUptime. You have been added to the on-call duty policy ${createdModel.onCallDutyPolicy?.name} for escalation rule ${createdModel.onCallDutyPolicyEscalationRule?.name} with order ${createdModel.onCallDutyPolicyEscalationRule?.order}. To unsubscribe from this notification go to User Settings in OneUptime Dashboard.`,
|
|
};
|
|
|
|
const callMessage: CallRequestMessage = {
|
|
data: [
|
|
{
|
|
sayMessage: `This is a message from OneUptime. You have been added to the on-call duty policy ${createdModel.onCallDutyPolicy?.name} for escalation rule ${createdModel.onCallDutyPolicyEscalationRule?.name} with order ${createdModel.onCallDutyPolicyEscalationRule?.order}. To unsubscribe from this notification go to User Settings in OneUptime Dashboard. Good Bye`,
|
|
},
|
|
],
|
|
};
|
|
|
|
const pushMessage: PushNotificationMessage =
|
|
PushNotificationUtil.createOnCallPolicyAddedNotification({
|
|
policyName: createdModel.onCallDutyPolicy?.name || "",
|
|
});
|
|
|
|
const eventType: NotificationSettingEventType =
|
|
NotificationSettingEventType.SEND_WHEN_USER_IS_ADDED_TO_ON_CALL_POLICY;
|
|
|
|
const whatsAppMessage: WhatsAppMessagePayload =
|
|
createWhatsAppMessageFromTemplate({
|
|
eventType,
|
|
templateVariables: {
|
|
on_call_policy_name:
|
|
createdModel.onCallDutyPolicy?.name || "No name provided",
|
|
on_call_context: `escalation rule ${createdModel.onCallDutyPolicyEscalationRule?.name || "No name provided"}`,
|
|
policy_link: vars["onCallPolicyViewLink"] || "",
|
|
},
|
|
});
|
|
|
|
await UserNotificationSettingService.sendUserNotification({
|
|
userId: sendEmailToUserId,
|
|
projectId: createdModel!.projectId!,
|
|
emailEnvelope: emailMessage,
|
|
smsMessage: sms,
|
|
callRequestMessage: callMessage,
|
|
pushNotificationMessage: pushMessage,
|
|
whatsAppMessage,
|
|
eventType,
|
|
onCallPolicyId: createdModel.onCallDutyPolicy!.id!,
|
|
onCallPolicyEscalationRuleId:
|
|
createdModel.onCallDutyPolicyEscalationRule!.id!,
|
|
});
|
|
|
|
// add workspace message.
|
|
|
|
const onCallDutyPolicyId: ObjectID | undefined | null =
|
|
createdModel.onCallDutyPolicy!.id;
|
|
const projectId: ObjectID | undefined = createdModel.projectId;
|
|
|
|
if (onCallDutyPolicyId) {
|
|
await OnCallDutyPolicyFeedService.createOnCallDutyPolicyFeedItem({
|
|
onCallDutyPolicyId: onCallDutyPolicyId,
|
|
projectId: projectId!,
|
|
onCallDutyPolicyFeedEventType: OnCallDutyPolicyFeedEventType.UserAdded,
|
|
displayColor: Gray500,
|
|
feedInfoInMarkdown: `👨🏻💻 Added **${await UserService.getUserMarkdownString(
|
|
{
|
|
userId: createdModel.user!.id!,
|
|
projectId: projectId!,
|
|
},
|
|
)}** to the [On-Call Policy ${createdModel.onCallDutyPolicy?.name}](${(await OnCallDutyPolicyService.getOnCallDutyPolicyLinkInDashboard(projectId!, onCallDutyPolicyId!)).toString()}) escalation rule **${createdModel.onCallDutyPolicyEscalationRule?.name}** with order **${createdModel.onCallDutyPolicyEscalationRule?.order}**.`,
|
|
userId: createdModel.createdByUserId! || undefined,
|
|
workspaceNotification: {
|
|
sendWorkspaceNotification: true,
|
|
notifyUserId: createdModel.createdByUserId! || undefined,
|
|
},
|
|
});
|
|
|
|
// also add on-call duty time log.
|
|
OnCallDutyPolicyTimeLogService.startTimeLogForUser({
|
|
projectId: projectId!,
|
|
onCallDutyPolicyId: onCallDutyPolicyId!,
|
|
onCallDutyPolicyEscalationRuleId:
|
|
createdModel.onCallDutyPolicyEscalationRule!.id!,
|
|
userId: createdModel.user!.id!,
|
|
startsAt: OneUptimeDate.getCurrentDate(),
|
|
}).catch((error: Error) => {
|
|
logger.error(
|
|
`Error starting time log for user ${createdModel.user?.id}: ${error}`,
|
|
);
|
|
});
|
|
}
|
|
|
|
return createdItem;
|
|
}
|
|
|
|
protected override async onBeforeDelete(
|
|
deleteBy: DeleteBy<Model>,
|
|
): Promise<OnDelete<Model>> {
|
|
const itemsToFetchBeforeDelete: Array<Model> = await this.findBy({
|
|
query: deleteBy.query,
|
|
props: {
|
|
isRoot: true,
|
|
},
|
|
select: {
|
|
projectId: true,
|
|
user: {
|
|
timezone: true,
|
|
_id: true,
|
|
},
|
|
onCallDutyPolicyEscalationRule: {
|
|
name: true,
|
|
_id: true,
|
|
order: true,
|
|
},
|
|
onCallDutyPolicy: {
|
|
name: true,
|
|
_id: true,
|
|
},
|
|
createdByUserId: true,
|
|
},
|
|
limit: LIMIT_PER_PROJECT,
|
|
skip: 0,
|
|
});
|
|
|
|
const deleteByUserId: ObjectID | undefined =
|
|
deleteBy.deletedByUser?.id || deleteBy.props.userId;
|
|
|
|
for (const item of itemsToFetchBeforeDelete) {
|
|
const onCallDutyPolicyId: ObjectID | undefined =
|
|
item.onCallDutyPolicy!.id!;
|
|
const projectId: ObjectID | undefined = item.projectId;
|
|
const userId: ObjectID | undefined = item.user!.id!;
|
|
|
|
if (onCallDutyPolicyId && userId && projectId) {
|
|
const user: User | null = await UserService.findOneById({
|
|
id: userId,
|
|
select: {
|
|
name: true,
|
|
email: true,
|
|
},
|
|
props: {
|
|
isRoot: true,
|
|
},
|
|
});
|
|
|
|
const onCallDutyPolicyName: string | null =
|
|
item.onCallDutyPolicy?.name || "No name provided";
|
|
|
|
if (user && user.name) {
|
|
await OnCallDutyPolicyFeedService.createOnCallDutyPolicyFeedItem({
|
|
onCallDutyPolicyId: onCallDutyPolicyId,
|
|
projectId: projectId,
|
|
onCallDutyPolicyFeedEventType:
|
|
OnCallDutyPolicyFeedEventType.OwnerUserRemoved,
|
|
displayColor: Red500,
|
|
feedInfoInMarkdown: `👨🏻💻 Removed **${user.name.toString()}** (${user.email?.toString()}) from the [On-Call Policy ${onCallDutyPolicyName}](${(await OnCallDutyPolicyService.getOnCallDutyPolicyLinkInDashboard(projectId!, onCallDutyPolicyId!)).toString()}) for escalation rule ${item.onCallDutyPolicyEscalationRule?.name} with order ${item.onCallDutyPolicyEscalationRule?.order}.`,
|
|
userId: deleteByUserId || undefined,
|
|
workspaceNotification: {
|
|
sendWorkspaceNotification: true,
|
|
notifyUserId: userId || undefined,
|
|
},
|
|
});
|
|
|
|
// also remove on-call duty time log.
|
|
OnCallDutyPolicyTimeLogService.endTimeLogForUser({
|
|
projectId: projectId,
|
|
onCallDutyPolicyId: onCallDutyPolicyId,
|
|
onCallDutyPolicyEscalationRuleId:
|
|
item.onCallDutyPolicyEscalationRule!.id!,
|
|
userId: userId,
|
|
endsAt: OneUptimeDate.getCurrentDate(),
|
|
}).catch((error: Error) => {
|
|
logger.error(`Error ending time log for user ${userId}: ${error}`);
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
return {
|
|
deleteBy,
|
|
carryForward: {
|
|
deletedItems: itemsToFetchBeforeDelete,
|
|
},
|
|
};
|
|
}
|
|
|
|
protected override async onDeleteSuccess(
|
|
onDelete: OnDelete<Model>,
|
|
_itemIdsBeforeDelete: Array<ObjectID>,
|
|
): Promise<OnDelete<Model>> {
|
|
const deletedItems: Array<Model> = onDelete.carryForward.deletedItems;
|
|
|
|
for (const deletedItem of deletedItems) {
|
|
const sendEmailToUserId: ObjectID | undefined | null =
|
|
deletedItem.user?.id;
|
|
|
|
if (!sendEmailToUserId) {
|
|
return onDelete;
|
|
}
|
|
|
|
const vars: Dictionary<string> = {
|
|
onCallPolicyName:
|
|
deletedItem.onCallDutyPolicy?.name || "No name provided",
|
|
escalationRuleName:
|
|
deletedItem.onCallDutyPolicyEscalationRule?.name ||
|
|
"No name provided",
|
|
escalationRuleOrder:
|
|
deletedItem.onCallDutyPolicyEscalationRule?.order?.toString() ||
|
|
"No order provided",
|
|
reason:
|
|
"You have been removed from the on-call duty policy escalation rule.",
|
|
onCallPolicyViewLink: (
|
|
await OnCallDutyPolicyService.getOnCallDutyPolicyLinkInDashboard(
|
|
deletedItem!.projectId!,
|
|
deletedItem.onCallDutyPolicy!.id!,
|
|
)
|
|
).toString(),
|
|
};
|
|
|
|
// current user changed, send alert the new current user.
|
|
const emailMessage: EmailEnvelope = {
|
|
templateType: EmailTemplateType.UserRemovedFromOnCallPolicy,
|
|
vars: vars,
|
|
subject: `You have been removed from the on-call duty policy ${deletedItem.onCallDutyPolicy?.name}`,
|
|
};
|
|
|
|
const sms: SMSMessage = {
|
|
message: `This is a message from OneUptime. You have been removed from the on-call duty policy ${deletedItem.onCallDutyPolicy?.name} for escalation rule ${deletedItem.onCallDutyPolicyEscalationRule?.name} with order ${deletedItem.onCallDutyPolicyEscalationRule?.order}. To unsubscribe from this notification go to User Settings in OneUptime Dashboard.`,
|
|
};
|
|
|
|
const callMessage: CallRequestMessage = {
|
|
data: [
|
|
{
|
|
sayMessage: `This is a message from OneUptime. You have been removed from the on-call duty policy ${deletedItem.onCallDutyPolicy?.name} for escalation rule ${deletedItem.onCallDutyPolicyEscalationRule?.name} with order ${deletedItem.onCallDutyPolicyEscalationRule?.order}. To unsubscribe from this notification go to User Settings in OneUptime Dashboard. Good Bye`,
|
|
},
|
|
],
|
|
};
|
|
|
|
const pushMessage: PushNotificationMessage =
|
|
PushNotificationUtil.createOnCallPolicyRemovedNotification({
|
|
policyName: deletedItem.onCallDutyPolicy?.name || "",
|
|
});
|
|
|
|
const eventType: NotificationSettingEventType =
|
|
NotificationSettingEventType.SEND_WHEN_USER_IS_REMOVED_FROM_ON_CALL_POLICY;
|
|
|
|
const whatsAppMessage: WhatsAppMessagePayload =
|
|
createWhatsAppMessageFromTemplate({
|
|
eventType,
|
|
templateVariables: {
|
|
on_call_policy_name:
|
|
deletedItem.onCallDutyPolicy?.name || "No name provided",
|
|
on_call_context: `escalation rule ${deletedItem.onCallDutyPolicyEscalationRule?.name || "No name provided"}`,
|
|
policy_link: vars["onCallPolicyViewLink"] || "",
|
|
},
|
|
});
|
|
|
|
UserNotificationSettingService.sendUserNotification({
|
|
userId: sendEmailToUserId,
|
|
projectId: deletedItem!.projectId!,
|
|
emailEnvelope: emailMessage,
|
|
smsMessage: sms,
|
|
callRequestMessage: callMessage,
|
|
pushNotificationMessage: pushMessage,
|
|
whatsAppMessage,
|
|
eventType,
|
|
onCallPolicyId: deletedItem.onCallDutyPolicy!.id!,
|
|
onCallPolicyEscalationRuleId:
|
|
deletedItem.onCallDutyPolicyEscalationRule!.id!,
|
|
});
|
|
}
|
|
|
|
return onDelete;
|
|
}
|
|
}
|
|
export default new Service();
|