diff --git a/apps/dokploy/server/api/routers/notification.ts b/apps/dokploy/server/api/routers/notification.ts index 09a2aed2a..34eed2ff1 100644 --- a/apps/dokploy/server/api/routers/notification.ts +++ b/apps/dokploy/server/api/routers/notification.ts @@ -1,522 +1,582 @@ import { - createDiscordNotification, - createEmailNotification, - createGotifyNotification, - createNtfyNotification, - createSlackNotification, - createTelegramNotification, - findNotificationById, - IS_CLOUD, - removeNotificationById, - sendDiscordNotification, - sendEmailNotification, - sendGotifyNotification, - sendNtfyNotification, - sendServerThresholdNotifications, - sendSlackNotification, - sendTelegramNotification, - updateDiscordNotification, - updateEmailNotification, - updateGotifyNotification, - updateNtfyNotification, - updateSlackNotification, - updateTelegramNotification, + createCustomNotification, + createDiscordNotification, + createEmailNotification, + createGotifyNotification, + createNtfyNotification, + createSlackNotification, + createTelegramNotification, + findNotificationById, + IS_CLOUD, + removeNotificationById, + sendCustomNotification, + sendDiscordNotification, + sendEmailNotification, + sendGotifyNotification, + sendNtfyNotification, + sendServerThresholdNotifications, + sendSlackNotification, + sendTelegramNotification, + updateCustomNotification, + updateDiscordNotification, + updateEmailNotification, + updateGotifyNotification, + updateNtfyNotification, + updateSlackNotification, + updateTelegramNotification, } from "@dokploy/server"; import { TRPCError } from "@trpc/server"; import { desc, eq, sql } from "drizzle-orm"; import { z } from "zod"; import { - adminProcedure, - createTRPCRouter, - protectedProcedure, - publicProcedure, + adminProcedure, + createTRPCRouter, + protectedProcedure, + publicProcedure, } from "@/server/api/trpc"; import { db } from "@/server/db"; import { - apiCreateDiscord, - apiCreateEmail, - apiCreateGotify, - apiCreateNtfy, - apiCreateSlack, - apiCreateTelegram, - apiFindOneNotification, - apiTestDiscordConnection, - apiTestEmailConnection, - apiTestGotifyConnection, - apiTestNtfyConnection, - apiTestSlackConnection, - apiTestTelegramConnection, - apiUpdateDiscord, - apiUpdateEmail, - apiUpdateGotify, - apiUpdateNtfy, - apiUpdateSlack, - apiUpdateTelegram, - notifications, - server, - users_temp, + apiCreateCustom, + apiCreateDiscord, + apiCreateEmail, + apiCreateGotify, + apiCreateNtfy, + apiCreateSlack, + apiCreateTelegram, + apiFindOneNotification, + apiTestCustomConnection, + apiTestDiscordConnection, + apiTestEmailConnection, + apiTestGotifyConnection, + apiTestNtfyConnection, + apiTestSlackConnection, + apiTestTelegramConnection, + apiUpdateCustom, + apiUpdateDiscord, + apiUpdateEmail, + apiUpdateGotify, + apiUpdateNtfy, + apiUpdateSlack, + apiUpdateTelegram, + notifications, + server, + users_temp, } from "@/server/db/schema"; export const notificationRouter = createTRPCRouter({ - createSlack: adminProcedure - .input(apiCreateSlack) - .mutation(async ({ input, ctx }) => { - try { - return await createSlackNotification( - input, - ctx.session.activeOrganizationId, - ); - } catch (error) { - throw new TRPCError({ - code: "BAD_REQUEST", - message: "Error creating the notification", - cause: error, - }); - } - }), - updateSlack: adminProcedure - .input(apiUpdateSlack) - .mutation(async ({ input, ctx }) => { - try { - const notification = await findNotificationById(input.notificationId); - if (notification.organizationId !== ctx.session.activeOrganizationId) { - throw new TRPCError({ - code: "UNAUTHORIZED", - message: "You are not authorized to update this notification", - }); - } - return await updateSlackNotification({ - ...input, - organizationId: ctx.session.activeOrganizationId, - }); - } catch (error) { - throw error; - } - }), - testSlackConnection: adminProcedure - .input(apiTestSlackConnection) - .mutation(async ({ input }) => { - try { - await sendSlackNotification(input, { - channel: input.channel, - text: "Hi, From Dokploy 👋", - }); - return true; - } catch (error) { - throw new TRPCError({ - code: "BAD_REQUEST", - message: "Error testing the notification", - cause: error, - }); - } - }), - createTelegram: adminProcedure - .input(apiCreateTelegram) - .mutation(async ({ input, ctx }) => { - try { - return await createTelegramNotification( - input, - ctx.session.activeOrganizationId, - ); - } catch (error) { - throw new TRPCError({ - code: "BAD_REQUEST", - message: "Error creating the notification", - cause: error, - }); - } - }), + createSlack: adminProcedure + .input(apiCreateSlack) + .mutation(async ({ input, ctx }) => { + try { + return await createSlackNotification( + input, + ctx.session.activeOrganizationId + ); + } catch (error) { + throw new TRPCError({ + code: "BAD_REQUEST", + message: "Error creating the notification", + cause: error, + }); + } + }), + updateSlack: adminProcedure + .input(apiUpdateSlack) + .mutation(async ({ input, ctx }) => { + try { + const notification = await findNotificationById(input.notificationId); + if (notification.organizationId !== ctx.session.activeOrganizationId) { + throw new TRPCError({ + code: "UNAUTHORIZED", + message: "You are not authorized to update this notification", + }); + } + return await updateSlackNotification({ + ...input, + organizationId: ctx.session.activeOrganizationId, + }); + } catch (error) { + throw error; + } + }), + testSlackConnection: adminProcedure + .input(apiTestSlackConnection) + .mutation(async ({ input }) => { + try { + await sendSlackNotification(input, { + channel: input.channel, + text: "Hi, From Dokploy 👋", + }); + return true; + } catch (error) { + throw new TRPCError({ + code: "BAD_REQUEST", + message: "Error testing the notification", + cause: error, + }); + } + }), + createTelegram: adminProcedure + .input(apiCreateTelegram) + .mutation(async ({ input, ctx }) => { + try { + return await createTelegramNotification( + input, + ctx.session.activeOrganizationId + ); + } catch (error) { + throw new TRPCError({ + code: "BAD_REQUEST", + message: "Error creating the notification", + cause: error, + }); + } + }), - updateTelegram: adminProcedure - .input(apiUpdateTelegram) - .mutation(async ({ input, ctx }) => { - try { - const notification = await findNotificationById(input.notificationId); - if (notification.organizationId !== ctx.session.activeOrganizationId) { - throw new TRPCError({ - code: "UNAUTHORIZED", - message: "You are not authorized to update this notification", - }); - } - return await updateTelegramNotification({ - ...input, - organizationId: ctx.session.activeOrganizationId, - }); - } catch (error) { - throw new TRPCError({ - code: "BAD_REQUEST", - message: "Error updating the notification", - cause: error, - }); - } - }), - testTelegramConnection: adminProcedure - .input(apiTestTelegramConnection) - .mutation(async ({ input }) => { - try { - await sendTelegramNotification(input, "Hi, From Dokploy 👋"); - return true; - } catch (error) { - throw new TRPCError({ - code: "BAD_REQUEST", - message: "Error testing the notification", - cause: error, - }); - } - }), - createDiscord: adminProcedure - .input(apiCreateDiscord) - .mutation(async ({ input, ctx }) => { - try { - return await createDiscordNotification( - input, - ctx.session.activeOrganizationId, - ); - } catch (error) { - throw new TRPCError({ - code: "BAD_REQUEST", - message: "Error creating the notification", - cause: error, - }); - } - }), + updateTelegram: adminProcedure + .input(apiUpdateTelegram) + .mutation(async ({ input, ctx }) => { + try { + const notification = await findNotificationById(input.notificationId); + if (notification.organizationId !== ctx.session.activeOrganizationId) { + throw new TRPCError({ + code: "UNAUTHORIZED", + message: "You are not authorized to update this notification", + }); + } + return await updateTelegramNotification({ + ...input, + organizationId: ctx.session.activeOrganizationId, + }); + } catch (error) { + throw new TRPCError({ + code: "BAD_REQUEST", + message: "Error updating the notification", + cause: error, + }); + } + }), + testTelegramConnection: adminProcedure + .input(apiTestTelegramConnection) + .mutation(async ({ input }) => { + try { + await sendTelegramNotification(input, "Hi, From Dokploy 👋"); + return true; + } catch (error) { + throw new TRPCError({ + code: "BAD_REQUEST", + message: "Error testing the notification", + cause: error, + }); + } + }), + createDiscord: adminProcedure + .input(apiCreateDiscord) + .mutation(async ({ input, ctx }) => { + try { + return await createDiscordNotification( + input, + ctx.session.activeOrganizationId + ); + } catch (error) { + throw new TRPCError({ + code: "BAD_REQUEST", + message: "Error creating the notification", + cause: error, + }); + } + }), - updateDiscord: adminProcedure - .input(apiUpdateDiscord) - .mutation(async ({ input, ctx }) => { - try { - const notification = await findNotificationById(input.notificationId); - if (notification.organizationId !== ctx.session.activeOrganizationId) { - throw new TRPCError({ - code: "UNAUTHORIZED", - message: "You are not authorized to update this notification", - }); - } - return await updateDiscordNotification({ - ...input, - organizationId: ctx.session.activeOrganizationId, - }); - } catch (error) { - throw new TRPCError({ - code: "BAD_REQUEST", - message: "Error updating the notification", - cause: error, - }); - } - }), + updateDiscord: adminProcedure + .input(apiUpdateDiscord) + .mutation(async ({ input, ctx }) => { + try { + const notification = await findNotificationById(input.notificationId); + if (notification.organizationId !== ctx.session.activeOrganizationId) { + throw new TRPCError({ + code: "UNAUTHORIZED", + message: "You are not authorized to update this notification", + }); + } + return await updateDiscordNotification({ + ...input, + organizationId: ctx.session.activeOrganizationId, + }); + } catch (error) { + throw new TRPCError({ + code: "BAD_REQUEST", + message: "Error updating the notification", + cause: error, + }); + } + }), - testDiscordConnection: adminProcedure - .input(apiTestDiscordConnection) - .mutation(async ({ input }) => { - try { - const decorate = (decoration: string, text: string) => - `${input.decoration ? decoration : ""} ${text}`.trim(); + testDiscordConnection: adminProcedure + .input(apiTestDiscordConnection) + .mutation(async ({ input }) => { + try { + const decorate = (decoration: string, text: string) => + `${input.decoration ? decoration : ""} ${text}`.trim(); - await sendDiscordNotification(input, { - title: decorate(">", "`🤚` - Test Notification"), - description: decorate(">", "Hi, From Dokploy 👋"), - color: 0xf3f7f4, - }); + await sendDiscordNotification(input, { + title: decorate(">", "`🤚` - Test Notification"), + description: decorate(">", "Hi, From Dokploy 👋"), + color: 0xf3f7f4, + }); - return true; - } catch (error) { - throw new TRPCError({ - code: "BAD_REQUEST", - message: "Error testing the notification", - cause: error, - }); - } - }), - createEmail: adminProcedure - .input(apiCreateEmail) - .mutation(async ({ input, ctx }) => { - try { - return await createEmailNotification( - input, - ctx.session.activeOrganizationId, - ); - } catch (error) { - throw new TRPCError({ - code: "BAD_REQUEST", - message: "Error creating the notification", - cause: error, - }); - } - }), - updateEmail: adminProcedure - .input(apiUpdateEmail) - .mutation(async ({ input, ctx }) => { - try { - const notification = await findNotificationById(input.notificationId); - if (notification.organizationId !== ctx.session.activeOrganizationId) { - throw new TRPCError({ - code: "UNAUTHORIZED", - message: "You are not authorized to update this notification", - }); - } - return await updateEmailNotification({ - ...input, - organizationId: ctx.session.activeOrganizationId, - }); - } catch (error) { - throw new TRPCError({ - code: "BAD_REQUEST", - message: "Error updating the notification", - cause: error, - }); - } - }), - testEmailConnection: adminProcedure - .input(apiTestEmailConnection) - .mutation(async ({ input }) => { - try { - await sendEmailNotification( - input, - "Test Email", - "
Hi, From Dokploy 👋
", - ); - return true; - } catch (error) { - throw new TRPCError({ - code: "BAD_REQUEST", - message: "Error testing the notification", - cause: error, - }); - } - }), - remove: adminProcedure - .input(apiFindOneNotification) - .mutation(async ({ input, ctx }) => { - try { - const notification = await findNotificationById(input.notificationId); - if (notification.organizationId !== ctx.session.activeOrganizationId) { - throw new TRPCError({ - code: "UNAUTHORIZED", - message: "You are not authorized to delete this notification", - }); - } - return await removeNotificationById(input.notificationId); - } catch (error) { - const message = - error instanceof Error - ? error.message - : "Error deleting this notification"; - throw new TRPCError({ - code: "BAD_REQUEST", - message, - }); - } - }), - one: protectedProcedure - .input(apiFindOneNotification) - .query(async ({ input, ctx }) => { - const notification = await findNotificationById(input.notificationId); - if (notification.organizationId !== ctx.session.activeOrganizationId) { - throw new TRPCError({ - code: "UNAUTHORIZED", - message: "You are not authorized to access this notification", - }); - } - return notification; - }), - all: adminProcedure.query(async ({ ctx }) => { - return await db.query.notifications.findMany({ - with: { - slack: true, - telegram: true, - discord: true, - email: true, - gotify: true, - ntfy: true, - }, - orderBy: desc(notifications.createdAt), - where: eq(notifications.organizationId, ctx.session.activeOrganizationId), - }); - }), - receiveNotification: publicProcedure - .input( - z.object({ - ServerType: z.enum(["Dokploy", "Remote"]).default("Dokploy"), - Type: z.enum(["Memory", "CPU"]), - Value: z.number(), - Threshold: z.number(), - Message: z.string(), - Timestamp: z.string(), - Token: z.string(), - }), - ) - .mutation(async ({ input }) => { - try { - let organizationId = ""; - let ServerName = ""; - if (input.ServerType === "Dokploy") { - const result = await db - .select() - .from(users_temp) - .where( - sql`${users_temp.metricsConfig}::jsonb -> 'server' ->> 'token' = ${input.Token}`, - ); + return true; + } catch (error) { + throw new TRPCError({ + code: "BAD_REQUEST", + message: "Error testing the notification", + cause: error, + }); + } + }), + createEmail: adminProcedure + .input(apiCreateEmail) + .mutation(async ({ input, ctx }) => { + try { + return await createEmailNotification( + input, + ctx.session.activeOrganizationId + ); + } catch (error) { + throw new TRPCError({ + code: "BAD_REQUEST", + message: "Error creating the notification", + cause: error, + }); + } + }), + updateEmail: adminProcedure + .input(apiUpdateEmail) + .mutation(async ({ input, ctx }) => { + try { + const notification = await findNotificationById(input.notificationId); + if (notification.organizationId !== ctx.session.activeOrganizationId) { + throw new TRPCError({ + code: "UNAUTHORIZED", + message: "You are not authorized to update this notification", + }); + } + return await updateEmailNotification({ + ...input, + organizationId: ctx.session.activeOrganizationId, + }); + } catch (error) { + throw new TRPCError({ + code: "BAD_REQUEST", + message: "Error updating the notification", + cause: error, + }); + } + }), + testEmailConnection: adminProcedure + .input(apiTestEmailConnection) + .mutation(async ({ input }) => { + try { + await sendEmailNotification( + input, + "Test Email", + "Hi, From Dokploy 👋
" + ); + return true; + } catch (error) { + throw new TRPCError({ + code: "BAD_REQUEST", + message: "Error testing the notification", + cause: error, + }); + } + }), + remove: adminProcedure + .input(apiFindOneNotification) + .mutation(async ({ input, ctx }) => { + try { + const notification = await findNotificationById(input.notificationId); + if (notification.organizationId !== ctx.session.activeOrganizationId) { + throw new TRPCError({ + code: "UNAUTHORIZED", + message: "You are not authorized to delete this notification", + }); + } + return await removeNotificationById(input.notificationId); + } catch (error) { + const message = + error instanceof Error + ? error.message + : "Error deleting this notification"; + throw new TRPCError({ + code: "BAD_REQUEST", + message, + }); + } + }), + one: protectedProcedure + .input(apiFindOneNotification) + .query(async ({ input, ctx }) => { + const notification = await findNotificationById(input.notificationId); + if (notification.organizationId !== ctx.session.activeOrganizationId) { + throw new TRPCError({ + code: "UNAUTHORIZED", + message: "You are not authorized to access this notification", + }); + } + return notification; + }), + all: adminProcedure.query(async ({ ctx }) => { + return await db.query.notifications.findMany({ + with: { + slack: true, + telegram: true, + discord: true, + email: true, + gotify: true, + ntfy: true, + custom: true, + }, + orderBy: desc(notifications.createdAt), + where: eq(notifications.organizationId, ctx.session.activeOrganizationId), + }); + }), + receiveNotification: publicProcedure + .input( + z.object({ + ServerType: z.enum(["Dokploy", "Remote"]).default("Dokploy"), + Type: z.enum(["Memory", "CPU"]), + Value: z.number(), + Threshold: z.number(), + Message: z.string(), + Timestamp: z.string(), + Token: z.string(), + }) + ) + .mutation(async ({ input }) => { + try { + let organizationId = ""; + let ServerName = ""; + if (input.ServerType === "Dokploy") { + const result = await db + .select() + .from(users_temp) + .where( + sql`${users_temp.metricsConfig}::jsonb -> 'server' ->> 'token' = ${input.Token}` + ); - if (!result?.[0]?.id) { - throw new TRPCError({ - code: "BAD_REQUEST", - message: "Token not found", - }); - } + if (!result?.[0]?.id) { + throw new TRPCError({ + code: "BAD_REQUEST", + message: "Token not found", + }); + } - organizationId = result?.[0]?.id; - ServerName = "Dokploy"; - } else { - const result = await db - .select() - .from(server) - .where( - sql`${server.metricsConfig}::jsonb -> 'server' ->> 'token' = ${input.Token}`, - ); + organizationId = result?.[0]?.id; + ServerName = "Dokploy"; + } else { + const result = await db + .select() + .from(server) + .where( + sql`${server.metricsConfig}::jsonb -> 'server' ->> 'token' = ${input.Token}` + ); - if (!result?.[0]?.organizationId) { - throw new TRPCError({ - code: "BAD_REQUEST", - message: "Token not found", - }); - } + if (!result?.[0]?.organizationId) { + throw new TRPCError({ + code: "BAD_REQUEST", + message: "Token not found", + }); + } - organizationId = result?.[0]?.organizationId; - ServerName = "Remote"; - } + organizationId = result?.[0]?.organizationId; + ServerName = "Remote"; + } - await sendServerThresholdNotifications(organizationId, { - ...input, - ServerName, - }); - } catch (error) { - throw new TRPCError({ - code: "BAD_REQUEST", - message: "Error sending the notification", - cause: error, - }); - } - }), - createGotify: adminProcedure - .input(apiCreateGotify) - .mutation(async ({ input, ctx }) => { - try { - return await createGotifyNotification( - input, - ctx.session.activeOrganizationId, - ); - } catch (error) { - throw new TRPCError({ - code: "BAD_REQUEST", - message: "Error creating the notification", - cause: error, - }); - } - }), - updateGotify: adminProcedure - .input(apiUpdateGotify) - .mutation(async ({ input, ctx }) => { - try { - const notification = await findNotificationById(input.notificationId); - if ( - IS_CLOUD && - notification.organizationId !== ctx.session.activeOrganizationId - ) { - throw new TRPCError({ - code: "UNAUTHORIZED", - message: "You are not authorized to update this notification", - }); - } - return await updateGotifyNotification({ - ...input, - organizationId: ctx.session.activeOrganizationId, - }); - } catch (error) { - throw error; - } - }), - testGotifyConnection: adminProcedure - .input(apiTestGotifyConnection) - .mutation(async ({ input }) => { - try { - await sendGotifyNotification( - input, - "Test Notification", - "Hi, From Dokploy 👋", - ); - return true; - } catch (error) { - throw new TRPCError({ - code: "BAD_REQUEST", - message: "Error testing the notification", - cause: error, - }); - } - }), - createNtfy: adminProcedure - .input(apiCreateNtfy) - .mutation(async ({ input, ctx }) => { - try { - return await createNtfyNotification( - input, - ctx.session.activeOrganizationId, - ); - } catch (error) { - throw new TRPCError({ - code: "BAD_REQUEST", - message: "Error creating the notification", - cause: error, - }); - } - }), - updateNtfy: adminProcedure - .input(apiUpdateNtfy) - .mutation(async ({ input, ctx }) => { - try { - const notification = await findNotificationById(input.notificationId); - if ( - IS_CLOUD && - notification.organizationId !== ctx.session.activeOrganizationId - ) { - throw new TRPCError({ - code: "UNAUTHORIZED", - message: "You are not authorized to update this notification", - }); - } - return await updateNtfyNotification({ - ...input, - organizationId: ctx.session.activeOrganizationId, - }); - } catch (error) { - throw error; - } - }), - testNtfyConnection: adminProcedure - .input(apiTestNtfyConnection) - .mutation(async ({ input }) => { - try { - await sendNtfyNotification( - input, - "Test Notification", - "", - "view, visit Dokploy on Github, https://github.com/dokploy/dokploy, clear=true;", - "Hi, From Dokploy 👋", - ); - return true; - } catch (error) { - throw new TRPCError({ - code: "BAD_REQUEST", - message: "Error testing the notification", - cause: error, - }); - } - }), - getEmailProviders: adminProcedure.query(async ({ ctx }) => { - return await db.query.notifications.findMany({ - where: eq(notifications.organizationId, ctx.session.activeOrganizationId), - with: { - email: true, - }, - }); - }), + await sendServerThresholdNotifications(organizationId, { + ...input, + ServerName, + }); + } catch (error) { + throw new TRPCError({ + code: "BAD_REQUEST", + message: "Error sending the notification", + cause: error, + }); + } + }), + createGotify: adminProcedure + .input(apiCreateGotify) + .mutation(async ({ input, ctx }) => { + try { + return await createGotifyNotification( + input, + ctx.session.activeOrganizationId + ); + } catch (error) { + throw new TRPCError({ + code: "BAD_REQUEST", + message: "Error creating the notification", + cause: error, + }); + } + }), + updateGotify: adminProcedure + .input(apiUpdateGotify) + .mutation(async ({ input, ctx }) => { + try { + const notification = await findNotificationById(input.notificationId); + if ( + IS_CLOUD && + notification.organizationId !== ctx.session.activeOrganizationId + ) { + throw new TRPCError({ + code: "UNAUTHORIZED", + message: "You are not authorized to update this notification", + }); + } + return await updateGotifyNotification({ + ...input, + organizationId: ctx.session.activeOrganizationId, + }); + } catch (error) { + throw error; + } + }), + testGotifyConnection: adminProcedure + .input(apiTestGotifyConnection) + .mutation(async ({ input }) => { + try { + await sendGotifyNotification( + input, + "Test Notification", + "Hi, From Dokploy 👋" + ); + return true; + } catch (error) { + throw new TRPCError({ + code: "BAD_REQUEST", + message: "Error testing the notification", + cause: error, + }); + } + }), + createNtfy: adminProcedure + .input(apiCreateNtfy) + .mutation(async ({ input, ctx }) => { + try { + return await createNtfyNotification( + input, + ctx.session.activeOrganizationId + ); + } catch (error) { + throw new TRPCError({ + code: "BAD_REQUEST", + message: "Error creating the notification", + cause: error, + }); + } + }), + updateNtfy: adminProcedure + .input(apiUpdateNtfy) + .mutation(async ({ input, ctx }) => { + try { + const notification = await findNotificationById(input.notificationId); + if ( + IS_CLOUD && + notification.organizationId !== ctx.session.activeOrganizationId + ) { + throw new TRPCError({ + code: "UNAUTHORIZED", + message: "You are not authorized to update this notification", + }); + } + return await updateNtfyNotification({ + ...input, + organizationId: ctx.session.activeOrganizationId, + }); + } catch (error) { + throw error; + } + }), + testNtfyConnection: adminProcedure + .input(apiTestNtfyConnection) + .mutation(async ({ input }) => { + try { + await sendNtfyNotification( + input, + "Test Notification", + "", + "view, visit Dokploy on Github, https://github.com/dokploy/dokploy, clear=true;", + "Hi, From Dokploy 👋" + ); + return true; + } catch (error) { + throw new TRPCError({ + code: "BAD_REQUEST", + message: "Error testing the notification", + cause: error, + }); + } + }), + createCustom: adminProcedure + .input(apiCreateCustom) + .mutation(async ({ input, ctx }) => { + try { + return await createCustomNotification( + input, + ctx.session.activeOrganizationId + ); + } catch (error) { + throw new TRPCError({ + code: "BAD_REQUEST", + message: "Error creating the notification", + cause: error, + }); + } + }), + updateCustom: adminProcedure + .input(apiUpdateCustom) + .mutation(async ({ input, ctx }) => { + try { + const notification = await findNotificationById(input.notificationId); + if (notification.organizationId !== ctx.session.activeOrganizationId) { + throw new TRPCError({ + code: "UNAUTHORIZED", + message: "You are not authorized to update this notification", + }); + } + return await updateCustomNotification({ + ...input, + organizationId: ctx.session.activeOrganizationId, + }); + } catch (error) { + throw error; + } + }), + testCustomConnection: adminProcedure + .input(apiTestCustomConnection) + .mutation(async ({ input }) => { + try { + await sendCustomNotification(input, { + title: "Test Notification", + message: "Hi, From Dokploy 👋", + timestamp: new Date().toISOString(), + }); + return true; + } catch (error) { + throw new TRPCError({ + code: "BAD_REQUEST", + message: "Error testing the notification", + cause: error, + }); + } + }), + getEmailProviders: adminProcedure.query(async ({ ctx }) => { + return await db.query.notifications.findMany({ + where: eq(notifications.organizationId, ctx.session.activeOrganizationId), + with: { + email: true, + }, + }); + }), });