refactor: Add notification webhook on user creation

This commit adds a notification webhook on user creation in the UserService. When a new user is created, a Slack message is sent to the specified webhook URL with details about the user's email, name, phone number, and company name. This feature enhances the user onboarding process and allows for better tracking and communication with new users.
This commit is contained in:
Simon Larsen 2024-06-25 22:48:46 +01:00
parent 2187edc158
commit e2074b010e
No known key found for this signature in database
GPG Key ID: 96C5DCA24769DBCA
8 changed files with 83 additions and 14 deletions

View File

@ -210,3 +210,6 @@ export const AllowedActiveMonitorCountInFreePlan: number = process.env[
process.env["ALLOWED_ACTIVE_MONITOR_COUNT_IN_FREE_PLAN"].toString(),
)
: 10;
export const NotificationWebhookOnCreateUser: string =
process.env["NOTIFICATION_WEBHOOK_ON_CREATED_USER"] || "";

View File

@ -1,7 +1,10 @@
import DatabaseConfig from "../DatabaseConfig";
import { IsBillingEnabled } from "../EnvironmentConfig";
import {
IsBillingEnabled,
NotificationWebhookOnCreateUser,
} from "../EnvironmentConfig";
import PostgresDatabase from "../Infrastructure/PostgresDatabase";
import { OnUpdate } from "../Types/Database/Hooks";
import { OnCreate, OnUpdate } from "../Types/Database/Hooks";
import UpdateBy from "../Types/Database/UpdateBy";
import logger from "../Utils/Logger";
import DatabaseService from "./DatabaseService";
@ -26,12 +29,35 @@ import Text from "Common/Types/Text";
import EmailVerificationToken from "Model/Models/EmailVerificationToken";
import TeamMember from "Model/Models/TeamMember";
import Model from "Model/Models/User";
import SlackUtil from "../Utils/Slack";
export class Service extends DatabaseService<Model> {
public constructor(postgresDatabase?: PostgresDatabase) {
super(Model, postgresDatabase);
}
protected override async onCreateSuccess(
_onCreate: OnCreate<Model>,
createdItem: Model,
): Promise<Model> {
if (NotificationWebhookOnCreateUser) {
SlackUtil.sendMessageToChannel({
url: URL.fromString(NotificationWebhookOnCreateUser),
text: `*New OneUptime User:*
*Email:* ${createdItem.email?.toString() || "N/A"}
*Name:* ${createdItem.name?.toString() || "N/A"}
*Phone:* ${createdItem.companyPhoneNumber?.toString() || "N/A"}
*Company:* ${createdItem.companyName?.toString() || "N/A"}`,
}).catch((err: Error) => {
// log this error but do not throw it. Not important enough to stop the process.
logger.error(err);
});
}
// A place holder method used for overriding.
return Promise.resolve(createdItem);
}
public async findByEmail(
email: Email,
props: DatabaseCommonInteractionProps,

View File

@ -8,7 +8,7 @@ import { JSONObject } from "Common/Types/JSON";
import ComponentMetadata, { Port } from "Common/Types/Workflow/Component";
import ComponentID from "Common/Types/Workflow/ComponentID";
import SlackComponents from "Common/Types/Workflow/Components/Slack";
import API from "Common/Utils/API";
import SlackUtil from "../../../../Utils/Slack";
export default class SendMessageToChannel extends ComponentCode {
public constructor() {
@ -69,16 +69,9 @@ export default class SendMessageToChannel extends ComponentCode {
try {
// https://api.slack.com/messaging/webhooks#advanced_message_formatting
apiResult = await API.post(args["webhook-url"] as URL, {
blocks: [
{
type: "section",
text: {
type: "mrkdwn",
text: `${args["text"]}`,
},
},
],
apiResult = await SlackUtil.sendMessageToChannel({
url: args["webhook-url"] as URL,
text: args["text"] as string,
});
if (apiResult instanceof HTTPErrorResponse) {

View File

@ -0,0 +1,29 @@
import HTTPErrorResponse from "Common/Types/API/HTTPErrorResponse";
import HTTPResponse from "Common/Types/API/HTTPResponse";
import URL from "Common/Types/API/URL";
import { JSONObject } from "Common/Types/JSON";
import API from "Common/Utils/API";
export default class SlackUtil {
public static async sendMessageToChannel(data: {
url: URL;
text: string;
}): Promise<HTTPResponse<JSONObject> | HTTPErrorResponse> {
let apiResult: HTTPResponse<JSONObject> | HTTPErrorResponse | null = null;
// https://api.slack.com/messaging/webhooks#advanced_message_formatting
apiResult = await API.post(data.url, {
blocks: [
{
type: "section",
text: {
type: "mrkdwn",
text: `${data.text}`,
},
},
],
});
return apiResult;
}
}

View File

@ -111,6 +111,9 @@ Usage:
- name: OPENTELEMETRY_EXPORTER_OTLP_ENDPOINT
value: {{ $.Values.openTelemetryExporter.endpoint.server }}
- name: NOTIFICATION_WEBHOOK_ON_CREATED_USER
value: {{ $.Values.notifications.webhooks.onCreateUser }}
- name: LETS_ENCRYPT_NOTIFICATION_EMAIL
value: {{ $.Values.letsEncrypt.email }}

View File

@ -338,4 +338,11 @@ externalClickhouse:
ca:
# (optional)
cert:
key:
key:
# Notification webhooks when certain events happen in the system. (usually they are slack webhooks)
notifications:
webhooks:
# This is the webhook that will be called when a user is created or signs up.
onCreateUser:

View File

@ -235,3 +235,8 @@ LETS_ENCRYPT_ACCOUNT_KEY=
# This is the number of active monitors allowed in the free plan.
ALLOWED_ACTIVE_MONITOR_COUNT_IN_FREE_PLAN=10
# Notifications Webhook (Slack)
# This webhook notifies slack when the new user signs up or is created.
NOTIFICATION_WEBHOOK_ON_CREATED_USER=

View File

@ -94,6 +94,9 @@ x-common-server-variables: &common-server-variables
DISABLE_AUTOMATIC_INCIDENT_CREATION: ${DISABLE_AUTOMATIC_INCIDENT_CREATION}
# Notification Webhooks
NOTIFICATION_WEBHOOK_ON_CREATED_USER: ${NOTIFICATION_WEBHOOK_ON_CREATED_USER}
services: