Feat/test channel (#371)

* add: test btn

* fix

* fix

---------

Co-authored-by: Théo LAGACHE <theo.lagache@soluce-technologies.com>
This commit is contained in:
Théo LAGACHE
2026-07-13 15:33:46 +02:00
committed by GitHub
co-authored by Théo LAGACHE
parent 3349bfaf3f
commit 1971ff69e3
58 changed files with 78 additions and 58 deletions
@@ -43,7 +43,7 @@ export const ChannelAddEditModal = ({
}: ChannelAddModalProps) => { }: ChannelAddModalProps) => {
const isMobile = useIsMobile(); const isMobile = useIsMobile();
const [openInternal, setOpen] = useState(open); const [openInternal, setOpen] = useState(open);
const isLocalSystem = channel?.provider == "local"; const isLocalSystem = channel?.provider === "local";
const isCreate = !Boolean(channel); const isCreate = !Boolean(channel);
@@ -33,7 +33,7 @@ export const EditChannelButton = ({
}: EditChannelButtonProps) => { }: EditChannelButtonProps) => {
const router = useRouter(); const router = useRouter();
const [isAddModalOpen, setIsAddModalOpen] = useState(false); const [isAddModalOpen, setIsAddModalOpen] = useState(false);
const isLocalSystem = channel.provider == "local"; const isLocalSystem = channel.provider === "local";
const mutation = useMutation({ const mutation = useMutation({
@@ -51,10 +51,10 @@ export const EditChannelButton = ({
}; };
let result: any; let result: any;
if (kind == "notification") { if (kind === "notification") {
// @ts-expect-error — payload type varies between notification and storage // @ts-expect-error — payload type varies between notification and storage
result = await updateNotificationChannelAction(payload) result = await updateNotificationChannelAction(payload)
} else if (kind == "storage") { } else if (kind === "storage") {
// @ts-expect-error — payload type varies between notification and storage // @ts-expect-error — payload type varies between notification and storage
result = await updateStorageChannelAction(payload) result = await updateStorageChannelAction(payload)
} else { } else {
@@ -224,13 +224,11 @@ export const ChannelForm = ({onSuccessAction, organization, defaultValues, kind}
<div className="flex justify-between mt-4"> <div className="flex justify-between mt-4">
<div> <div>
{(!isCreate || kind == "storage") && ( <ChannelTestButton
<ChannelTestButton kind={kind}
kind={kind} organizationId={organization?.id}
organizationId={organization?.id} channel={form.getValues()}
channel={form.getValues()} />
/>
)}
</div> </div>
<div className="flex gap-2"> <div className="flex gap-2">
<Button <Button
@@ -13,6 +13,7 @@ import {cn} from "@/lib/utils";
import {StorageChannel} from "@/db/schema/12_storage-channel"; import {StorageChannel} from "@/db/schema/12_storage-channel";
import {ChannelKind} from "@/features/channel/components/channels-helpers"; import {ChannelKind} from "@/features/channel/components/channels-helpers";
import type {StorageInput} from "@/features/storages/types"; import type {StorageInput} from "@/features/storages/types";
import type {NotificationChannelFormType} from "@/features/channel/schemas/channel-form.schema";
import {dispatchStorage} from "@/features/storages/utils/storages.dispatch"; import {dispatchStorage} from "@/features/storages/utils/storages.dispatch";
@@ -34,7 +35,7 @@ export const ChannelTestButton = ({channel, organizationId, kind}: NotifierTestC
message: `We are testing channel ${channel.name}`, message: `We are testing channel ${channel.name}`,
level: 'info', level: 'info',
}; };
const result = await dispatchNotification(payload, undefined, channel.id, organizationId); const result = await dispatchNotification(payload, undefined, undefined, organizationId, channel as unknown as NotificationChannelFormType);
if (result.success) { if (result.success) {
toast.success(result.message); toast.success(result.message);
@@ -1,49 +1,49 @@
import {UseFormReturn} from "react-hook-form"; import {UseFormReturn} from "react-hook-form";
import { import {
NotifierSmtpForm NotifierSmtpForm
} from "@/features/channel/components/notifications/smtp.form"; } from "@/features/channel/components/notifications/smtp/smtp.form";
import { import {
NotifierSlackForm NotifierSlackForm
} from "@/features/channel/components/notifications/slack.form"; } from "@/features/channel/components/notifications/slack/slack.form";
import { import {
NotifierDiscordForm NotifierDiscordForm
} from "@/features/channel/components/notifications/discord.form"; } from "@/features/channel/components/notifications/discord/discord.form";
import { import {
NotifierTelegramForm NotifierTelegramForm
} from "@/features/channel/components/notifications/telegram.form"; } from "@/features/channel/components/notifications/telegram/telegram.form";
import { import {
NotifierGotifyForm NotifierGotifyForm
} from "@/features/channel/components/notifications/gotify.form"; } from "@/features/channel/components/notifications/gotify/gotify.form";
import { import {
NotifierNtfyForm NotifierNtfyForm
} from "@/features/channel/components/notifications/ntfy.form"; } from "@/features/channel/components/notifications/ntfy/ntfy.form";
import { import {
NotifierWebhookForm NotifierWebhookForm
} from "@/features/channel/components/notifications/webhook.form"; } from "@/features/channel/components/notifications/webhook/webhook.form";
import { import {
NotifierNextcloudForm NotifierNextcloudForm
} from "@/features/channel/components/notifications/nextcloud.form"; } from "@/features/channel/components/notifications/nextcloud/nextcloud.form";
import { import {
NotifierPushoverForm NotifierPushoverForm
} from "@/features/channel/components/notifications/pushover.form"; } from "@/features/channel/components/notifications/pushover/pushover.form";
import { import {
notificationProviders, notificationProviders,
} from "@/features/channel/components/channels-notification-helper"; } from "@/features/channel/components/channels-notification-helper";
import { import {
NotifierTeamsForm NotifierTeamsForm
} from "@/features/channel/components/notifications/teams.form"; } from "@/features/channel/components/notifications/teams/teams.form";
import {storageProviders} from "@/features/channel/components/channels-storage-helper"; import {storageProviders} from "@/features/channel/components/channels-storage-helper";
import {ForwardRefExoticComponent, JSX, RefAttributes, SVGProps} from "react"; import {ForwardRefExoticComponent, JSX, RefAttributes, SVGProps} from "react";
import {LucideProps} from "lucide-react"; import {LucideProps} from "lucide-react";
import { import {
StorageS3Form StorageS3Form
} from "@/features/channel/components/storages/s3.form"; } from "@/features/channel/components/storages/s3/s3.form";
import { import {
StorageGoogleDriveForm StorageGoogleDriveForm
} from "@/features/channel/components/storages/google-drive/google-drive.form"; } from "@/features/channel/components/storages/google-drive/google-drive.form";
import { import {
StorageBlobForm StorageBlobForm
} from "@/features/channel/components/storages/az-blob.form"; } from "@/features/channel/components/storages/az-blob/az-blob.form";
import { import {
StorageGoogleCloudStorageForm StorageGoogleCloudStorageForm
} from "@/features/channel/components/storages/google-cloud-storage/google-cloud-storage.form"; } from "@/features/channel/components/storages/google-cloud-storage/google-cloud-storage.form";
@@ -0,0 +1 @@
export * from "./discord";
@@ -0,0 +1 @@
export * from "./gotify";
@@ -0,0 +1 @@
export * from "./nextcloud";
@@ -0,0 +1 @@
export * from "./ntfy";
@@ -0,0 +1 @@
export * from "./pushover";
@@ -4,7 +4,7 @@ import {Input} from "@/components/ui/input";
import {Separator} from "@/components/ui/separator"; import {Separator} from "@/components/ui/separator";
import {PasswordInput} from "@/components/ui/password-input"; import {PasswordInput} from "@/components/ui/password-input";
import {Select, SelectContent, SelectItem, SelectTrigger, SelectValue} from "@/components/ui/select"; import {Select, SelectContent, SelectItem, SelectTrigger, SelectValue} from "@/components/ui/select";
import {PUSHOVER_PRIORITIES} from "@/features/channel/components/notifications/pushover.schema"; import {PUSHOVER_PRIORITIES} from "@/features/channel/components/notifications/pushover/pushover.schema";
type NotifierPushoverFormProps = { type NotifierPushoverFormProps = {
form: UseFormReturn<any, any, any>; form: UseFormReturn<any, any, any>;
@@ -0,0 +1 @@
export * from "./slack";
@@ -0,0 +1 @@
export * from "./smtp";
@@ -0,0 +1 @@
export * from "./teams";
@@ -0,0 +1 @@
export * from "./telegram";
@@ -0,0 +1 @@
export * from "./webhook";
@@ -0,0 +1 @@
export * from "./az-blob";
@@ -0,0 +1 @@
export * from "./local";
@@ -0,0 +1 @@
export * from "./s3";
@@ -1,18 +1,18 @@
import {z} from "zod"; import {z} from "zod";
import {SlackChannelConfigSchema} from "@/features/channel/components/notifications/slack.schema"; import {SlackChannelConfigSchema} from "@/features/channel/components/notifications/slack/slack.schema";
import {SmtpChannelConfigSchema} from "@/features/channel/components/notifications/smtp.schema"; import {SmtpChannelConfigSchema} from "@/features/channel/components/notifications/smtp/smtp.schema";
import {DiscordChannelConfigSchema} from "@/features/channel/components/notifications/discord.schema"; import {DiscordChannelConfigSchema} from "@/features/channel/components/notifications/discord/discord.schema";
import {TelegramChannelConfigSchema} from "@/features/channel/components/notifications/telegram.schema"; import {TelegramChannelConfigSchema} from "@/features/channel/components/notifications/telegram/telegram.schema";
import {GotifyChannelConfigSchema} from "@/features/channel/components/notifications/gotify.schema"; import {GotifyChannelConfigSchema} from "@/features/channel/components/notifications/gotify/gotify.schema";
import {NtfyChannelConfigSchema} from "@/features/channel/components/notifications/ntfy.schema"; import {NtfyChannelConfigSchema} from "@/features/channel/components/notifications/ntfy/ntfy.schema";
import {WebhookChannelConfigSchema} from "@/features/channel/components/notifications/webhook.schema"; import {WebhookChannelConfigSchema} from "@/features/channel/components/notifications/webhook/webhook.schema";
import {NextcloudChannelConfigSchema} from "@/features/channel/components/notifications/nextcloud.schema"; import {NextcloudChannelConfigSchema} from "@/features/channel/components/notifications/nextcloud/nextcloud.schema";
import {PushoverChannelConfigSchema} from "@/features/channel/components/notifications/pushover.schema"; import {PushoverChannelConfigSchema} from "@/features/channel/components/notifications/pushover/pushover.schema";
import {S3ChannelConfigSchema} from "@/features/channel/components/storages/s3.schema"; import {S3ChannelConfigSchema} from "@/features/channel/components/storages/s3/s3.schema";
import {GoogleDriveChannelConfigSchema} from "@/features/channel/components/storages/google-drive/google-drive.schema"; import {GoogleDriveChannelConfigSchema} from "@/features/channel/components/storages/google-drive/google-drive.schema";
import {LocalChannelConfigSchema} from "@/features/channel/components/storages/local.schema"; import {LocalChannelConfigSchema} from "@/features/channel/components/storages/local/local.schema";
import {TeamsChannelConfigSchema} from "@/features/channel/components/notifications/teams.schema"; import {TeamsChannelConfigSchema} from "@/features/channel/components/notifications/teams/teams.schema";
import {BlobChannelConfigSchema} from "@/features/channel/components/storages/az-blob.schema"; import {BlobChannelConfigSchema} from "@/features/channel/components/storages/az-blob/az-blob.schema";
import { import {
GoogleCloudStorageChannelConfigSchema GoogleCloudStorageChannelConfigSchema
} from "@/features/channel/components/storages/google-cloud-storage/google-cloud-storage.schema"; } from "@/features/channel/components/storages/google-cloud-storage/google-cloud-storage.schema";
@@ -6,13 +6,15 @@ import * as drizzleDb from "@/db";
import {db} from "@/db"; import {db} from "@/db";
import {notificationLog} from "@/db/schema/11_notification-log"; import {notificationLog} from "@/db/schema/11_notification-log";
import {NotificationChannel} from "@/db/schema/09_notification-channel"; import {NotificationChannel} from "@/db/schema/09_notification-channel";
import {NotificationChannelFormType} from "@/features/channel/schemas/channel-form.schema";
import {Json} from "drizzle-zod"; import {Json} from "drizzle-zod";
export async function dispatchNotification( export async function dispatchNotification(
payload: EventPayload, payload: EventPayload,
policyId?: string, policyId?: string,
channelId?: string, channelId?: string,
organizationId?: string organizationId?: string,
channelData?: NotificationChannelFormType
): Promise<DispatchResult> { ): Promise<DispatchResult> {
try { try {
let channel: NotificationChannel | null = null; let channel: NotificationChannel | null = null;
@@ -69,6 +71,10 @@ export async function dispatchNotification(
}; };
} }
if (channelData) {
channel = {...channelData, config: channelData.config as Json};
}
if (!channel) { if (!channel) {
return { return {
success: false, success: false,
@@ -95,28 +101,30 @@ export async function dispatchNotification(
channel.id channel.id
); );
const [log] = await db if (!channelData) {
.insert(notificationLog) await db
.values({ .insert(notificationLog)
channelId: channel.id, .values({
policyId: policyId || null, channelId: channel.id,
organizationId: organizationId || null, policyId: policyId || null,
organizationId: organizationId || null,
provider: channel.provider, provider: channel.provider,
providerName: channel.name, providerName: channel.name,
event: payload.event as EventKind, event: payload.event as EventKind,
title: payload.title, title: payload.title,
message: payload.message, message: payload.message,
level: payload.level, level: payload.level,
payload: payload.data || null, payload: payload.data || null,
success: result.success, success: result.success,
error: result.success ? null : result.error, error: result.success ? null : result.error,
providerResponse: result.response || null, providerResponse: result.response || null,
}) })
.returning({id: notificationLog.id}); .returning({id: notificationLog.id});
}
return {...result, channelId: channel.id}; return {...result, channelId: channel.id ?? ""};
} catch (err: any) { } catch (err: any) {
return { return {