diff --git a/client/src/Hooks/useNotificationForm.ts b/client/src/Hooks/useNotificationForm.ts index 0051ddafdf..5c70040238 100644 --- a/client/src/Hooks/useNotificationForm.ts +++ b/client/src/Hooks/useNotificationForm.ts @@ -44,6 +44,10 @@ function buildDefaults(data: Notification | null): NotificationFormData { type: "webhook", notificationName: data.notificationName || "", address: data.address || "", + webhookAuthType: data.webhookAuthType || "none", + webhookUsername: data.webhookUsername || "", + webhookPassword: data.webhookPassword || "", + webhookToken: data.webhookToken || "", }; } if (data?.type === "pager_duty") { diff --git a/client/src/Pages/Notifications/create/index.tsx b/client/src/Pages/Notifications/create/index.tsx index 84d2646168..b8511458bd 100644 --- a/client/src/Pages/Notifications/create/index.tsx +++ b/client/src/Pages/Notifications/create/index.tsx @@ -175,6 +175,92 @@ const NotificationsCreatePage = () => { } /> )} + {watchedType === "webhook" && ( + + ( + + )} + /> + {watch("webhookAuthType") === "basic" && ( + <> + ( + + )} + /> + ( + + )} + /> + + )} + {watch("webhookAuthType") === "bearer" && ( + ( + + )} + /> + )} + + } + /> + )} {watchedType === "ntfy" && ( ( accountSid: { type: String }, twilioPhoneNumber: { type: String }, topic: { type: String }, + webhookAuthType: { type: String, enum: ['none', 'basic', 'bearer'] }, + webhookUsername: { type: String }, + webhookPassword: { type: String }, + webhookToken: { type: String }, }, { timestamps: true, diff --git a/server/src/domain/notifications/notification.type.ts b/server/src/domain/notifications/notification.type.ts index 8ae617a883..ec80587f66 100644 --- a/server/src/domain/notifications/notification.type.ts +++ b/server/src/domain/notifications/notification.type.ts @@ -27,6 +27,10 @@ export interface Notification { accountSid?: string; twilioPhoneNumber?: string; topic?: string; + webhookAuthType?: 'none' | 'basic' | 'bearer'; + webhookUsername?: string; + webhookPassword?: string; + webhookToken?: string; createdAt: string; updatedAt: string; } diff --git a/server/src/domain/notifications/providers/webhook.ts b/server/src/domain/notifications/providers/webhook.ts index fc5a80fdeb..b068e13804 100644 --- a/server/src/domain/notifications/providers/webhook.ts +++ b/server/src/domain/notifications/providers/webhook.ts @@ -6,6 +6,25 @@ import { getTestMessage } from "@/domain/notifications/providers/utils.js"; import got from "got"; export class WebhookProvider extends NotificationProvider { + /** + * Build authorization header based on webhook auth configuration + */ + private buildAuthHeaders = (notification: Notification): Record => { + const headers: Record = {}; + + if (notification.webhookAuthType === "basic") { + const username = notification.webhookUsername || ""; + const password = notification.webhookPassword || ""; + const encoded = Buffer.from(username + ":" + password).toString("base64"); + headers["Authorization"] = "Basic " + encoded; + } else if (notification.webhookAuthType === "bearer") { + const token = notification.webhookToken || ""; + headers["Authorization"] = "Bearer " + token; + } + + return headers; + }; + sendMessage = async (notification: Notification, message: NotificationMessage): Promise => { if (!notification.address) { return false; @@ -19,6 +38,7 @@ export class WebhookProvider extends NotificationProvider { json: payload, headers: { "Content-Type": "application/json", + ...this.buildAuthHeaders(notification), }, ...this.gotRequestOptions(), }); @@ -101,6 +121,7 @@ export class WebhookProvider extends NotificationProvider { json: { text: getTestMessage() }, headers: { "Content-Type": "application/json", + ...this.buildAuthHeaders(notification as Notification), }, ...this.gotRequestOptions(), });