From e645b31b32bcae0b9c52e6a78272155ea05477be Mon Sep 17 00:00:00 2001 From: Jonathan de Jong Date: Tue, 26 Aug 2025 07:53:20 +0200 Subject: [PATCH 01/55] change gitea permissions to new instances (#1832) --- apps/dokploy/utils/gitea-utils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/dokploy/utils/gitea-utils.ts b/apps/dokploy/utils/gitea-utils.ts index ab7b82dcc..6099aaa45 100644 --- a/apps/dokploy/utils/gitea-utils.ts +++ b/apps/dokploy/utils/gitea-utils.ts @@ -22,7 +22,7 @@ export const getGiteaOAuthUrl = ( } const redirectUri = `${baseUrl}/api/providers/gitea/callback`; - const scopes = "repo repo:status read:user read:org"; + const scopes = "read:repository read:user read:organization"; return `${giteaUrl}/login/oauth/authorize?client_id=${clientId}&redirect_uri=${encodeURIComponent( redirectUri, From b4a3cbdff4ad37c4d75df0526a90ccab4ccba3f3 Mon Sep 17 00:00:00 2001 From: ischanx Date: Wed, 24 Sep 2025 00:14:06 +0800 Subject: [PATCH 02/55] feat(notifications): add lark webhook --- .../notifications/handle-notifications.tsx | 74 +- .../notifications/show-notifications.tsx | 8 +- .../components/icons/notification-icons.tsx | 27 + apps/dokploy/drizzle/0113_lark_webhook.sql | 13 + apps/dokploy/drizzle/meta/0113_snapshot.json | 6616 +++++++++++++++++ apps/dokploy/drizzle/meta/_journal.json | 7 + .../server/api/routers/notification.ts | 64 + packages/server/src/db/schema/notification.ts | 41 + packages/server/src/services/notification.ts | 92 + .../src/utils/notifications/build-error.ts | 134 +- .../src/utils/notifications/build-success.ts | 122 +- .../utils/notifications/database-backup.ts | 160 +- .../src/utils/notifications/docker-cleanup.ts | 84 +- .../utils/notifications/dokploy-restart.ts | 80 +- .../utils/notifications/server-threshold.ts | 100 +- .../server/src/utils/notifications/utils.ts | 16 + 16 files changed, 7591 insertions(+), 47 deletions(-) create mode 100644 apps/dokploy/drizzle/0113_lark_webhook.sql create mode 100644 apps/dokploy/drizzle/meta/0113_snapshot.json diff --git a/apps/dokploy/components/dashboard/settings/notifications/handle-notifications.tsx b/apps/dokploy/components/dashboard/settings/notifications/handle-notifications.tsx index 4e4171bee..c923419c7 100644 --- a/apps/dokploy/components/dashboard/settings/notifications/handle-notifications.tsx +++ b/apps/dokploy/components/dashboard/settings/notifications/handle-notifications.tsx @@ -12,6 +12,7 @@ import { toast } from "sonner"; import { z } from "zod"; import { DiscordIcon, + LarkIcon, SlackIcon, TelegramIcon, } from "@/components/icons/notification-icons"; @@ -110,6 +111,12 @@ export const notificationSchema = z.discriminatedUnion("type", [ priority: z.number().min(1).max(5).default(3), }) .merge(notificationBaseSchema), + z + .object({ + type: z.literal("lark"), + webhookUrl: z.string().min(1, { message: "Webhook URL is required" }), + }) + .merge(notificationBaseSchema), ]); export const notificationsMap = { @@ -125,6 +132,10 @@ export const notificationsMap = { icon: , label: "Discord", }, + lark: { + icon: , + label: "Lark", + }, email: { icon: , label: "Email", @@ -170,6 +181,8 @@ export const HandleNotifications = ({ notificationId }: Props) => { api.notification.testGotifyConnection.useMutation(); const { mutateAsync: testNtfyConnection, isLoading: isLoadingNtfy } = api.notification.testNtfyConnection.useMutation(); + const { mutateAsync: testLarkConnection, isLoading: isLoadingLark } = + api.notification.testLarkConnection.useMutation(); const slackMutation = notificationId ? api.notification.updateSlack.useMutation() : api.notification.createSlack.useMutation(); @@ -188,6 +201,9 @@ export const HandleNotifications = ({ notificationId }: Props) => { const ntfyMutation = notificationId ? api.notification.updateNtfy.useMutation() : api.notification.createNtfy.useMutation(); + const larkMutation = notificationId + ? api.notification.updateLark.useMutation() + : api.notification.createLark.useMutation(); const form = useForm({ defaultValues: { @@ -297,6 +313,19 @@ export const HandleNotifications = ({ notificationId }: Props) => { serverUrl: notification.ntfy?.serverUrl, name: notification.name, dockerCleanup: notification.dockerCleanup, + serverThreshold: notification.serverThreshold, + }); + } else if (notification.notificationType === "lark") { + form.reset({ + appBuildError: notification.appBuildError, + appDeploy: notification.appDeploy, + dokployRestart: notification.dokployRestart, + databaseBackup: notification.databaseBackup, + type: notification.notificationType, + webhookUrl: notification.lark?.webhookUrl, + name: notification.name, + dockerCleanup: notification.dockerCleanup, + serverThreshold: notification.serverThreshold, }); } } else { @@ -311,6 +340,7 @@ export const HandleNotifications = ({ notificationId }: Props) => { email: emailMutation, gotify: gotifyMutation, ntfy: ntfyMutation, + lark: larkMutation, }; const onSubmit = async (data: NotificationSchema) => { @@ -413,6 +443,20 @@ export const HandleNotifications = ({ notificationId }: Props) => { dockerCleanup: dockerCleanup, notificationId: notificationId || "", ntfyId: notification?.ntfyId || "", + serverThreshold: serverThreshold, + }); + } else if (data.type === "lark") { + promise = larkMutation.mutateAsync({ + appBuildError: appBuildError, + appDeploy: appDeploy, + dokployRestart: dokployRestart, + databaseBackup: databaseBackup, + webhookUrl: data.webhookUrl, + name: data.name, + dockerCleanup: dockerCleanup, + notificationId: notificationId || "", + larkId: notification?.larkId || "", + serverThreshold: serverThreshold, }); } @@ -502,7 +546,7 @@ export const HandleNotifications = ({ notificationId }: Props) => { />