From 74374bd643d43bfef65168c9422b6a5b2fb7a1fd Mon Sep 17 00:00:00 2001 From: Krzysztof Durek <21038648+kdurek@users.noreply.github.com> Date: Sun, 17 Nov 2024 18:18:00 +0100 Subject: [PATCH 1/6] feat: add update server ip --- .../servers/actions/show-dokploy-actions.tsx | 19 ++- .../servers/actions/show-server-actions.tsx | 5 +- .../servers/actions/show-storage-actions.tsx | 8 +- .../servers/actions/show-traefik-actions.tsx | 10 +- .../settings/web-server/show-modal-logs.tsx | 9 +- .../settings/web-server/update-server-ip.tsx | 125 ++++++++++++++++++ .../settings/web-server/update-server.tsx | 2 +- apps/dokploy/server/api/routers/admin.ts | 8 ++ packages/server/src/db/schema/admin.ts | 2 + 9 files changed, 168 insertions(+), 20 deletions(-) create mode 100644 apps/dokploy/components/dashboard/settings/web-server/update-server-ip.tsx diff --git a/apps/dokploy/components/dashboard/settings/servers/actions/show-dokploy-actions.tsx b/apps/dokploy/components/dashboard/settings/servers/actions/show-dokploy-actions.tsx index 49f6772b5..9c30c13f7 100644 --- a/apps/dokploy/components/dashboard/settings/servers/actions/show-dokploy-actions.tsx +++ b/apps/dokploy/components/dashboard/settings/servers/actions/show-dokploy-actions.tsx @@ -1,6 +1,7 @@ import { Button } from "@/components/ui/button"; import React from "react"; +import { UpdateServerIp } from "@/components/dashboard/settings/web-server/update-server-ip"; import { DropdownMenu, DropdownMenuContent, @@ -39,12 +40,26 @@ export const ShowDokployActions = () => { toast.success("Server Reloaded"); }); }} + className="cursor-pointer" > - Reload + Reload - Watch logs + e.preventDefault()} + > + Watch Logs + + + e.preventDefault()} + > + Update Server IP + + diff --git a/apps/dokploy/components/dashboard/settings/servers/actions/show-server-actions.tsx b/apps/dokploy/components/dashboard/settings/servers/actions/show-server-actions.tsx index 1f7f2d146..fcc0e315f 100644 --- a/apps/dokploy/components/dashboard/settings/servers/actions/show-server-actions.tsx +++ b/apps/dokploy/components/dashboard/settings/servers/actions/show-server-actions.tsx @@ -1,4 +1,3 @@ -import { CardDescription, CardTitle } from "@/components/ui/card"; import { Dialog, DialogContent, @@ -21,13 +20,13 @@ export const ShowServerActions = ({ serverId }: Props) => { e.preventDefault()} > View Actions - +
Web server settings Reload or clean the web server. diff --git a/apps/dokploy/components/dashboard/settings/servers/actions/show-storage-actions.tsx b/apps/dokploy/components/dashboard/settings/servers/actions/show-storage-actions.tsx index b3f9c3345..4294d7d76 100644 --- a/apps/dokploy/components/dashboard/settings/servers/actions/show-storage-actions.tsx +++ b/apps/dokploy/components/dashboard/settings/servers/actions/show-storage-actions.tsx @@ -85,7 +85,7 @@ export const ShowStorageActions = ({ serverId }: Props) => { }); }} > - Clean unused images + Clean Unused Images { }); }} > - Clean unused volumes + Clean Unused Volumes { }); }} > - Clean stopped containers + Clean Stopped Containers { }); }} > - Clean all + Clean All diff --git a/apps/dokploy/components/dashboard/settings/servers/actions/show-traefik-actions.tsx b/apps/dokploy/components/dashboard/settings/servers/actions/show-traefik-actions.tsx index a0ea3f5e8..d37e3aba9 100644 --- a/apps/dokploy/components/dashboard/settings/servers/actions/show-traefik-actions.tsx +++ b/apps/dokploy/components/dashboard/settings/servers/actions/show-traefik-actions.tsx @@ -70,16 +70,22 @@ export const ShowTraefikActions = ({ serverId }: Props) => { toast.error("Error to reload the traefik"); }); }} + className="cursor-pointer" > Reload - Watch logs + e.preventDefault()} + className="cursor-pointer" + > + Watch Logs + e.preventDefault()} - className="w-full cursor-pointer space-x-3" + className="cursor-pointer" > Modify Env diff --git a/apps/dokploy/components/dashboard/settings/web-server/show-modal-logs.tsx b/apps/dokploy/components/dashboard/settings/web-server/show-modal-logs.tsx index 607ff7b2f..2693f79c0 100644 --- a/apps/dokploy/components/dashboard/settings/web-server/show-modal-logs.tsx +++ b/apps/dokploy/components/dashboard/settings/web-server/show-modal-logs.tsx @@ -58,14 +58,7 @@ export const ShowModalLogs = ({ appName, children, serverId }: Props) => { }, [data]); return ( - - e.preventDefault()} - > - {children} - - + {children} View Logs diff --git a/apps/dokploy/components/dashboard/settings/web-server/update-server-ip.tsx b/apps/dokploy/components/dashboard/settings/web-server/update-server-ip.tsx new file mode 100644 index 000000000..4834ef929 --- /dev/null +++ b/apps/dokploy/components/dashboard/settings/web-server/update-server-ip.tsx @@ -0,0 +1,125 @@ +import { AlertBlock } from "@/components/shared/alert-block"; +import { CodeEditor } from "@/components/shared/code-editor"; +import { Button } from "@/components/ui/button"; +import { + Dialog, + DialogContent, + DialogDescription, + DialogFooter, + DialogHeader, + DialogTitle, + DialogTrigger, +} from "@/components/ui/dialog"; +import { + Form, + FormControl, + FormField, + FormItem, + FormLabel, + FormMessage, +} from "@/components/ui/form"; +import { Input } from "@/components/ui/input"; +import { api } from "@/utils/api"; +import { zodResolver } from "@hookform/resolvers/zod"; +import { useEffect, useState } from "react"; +import { useForm } from "react-hook-form"; +import { toast } from "sonner"; +import { z } from "zod"; + +const schema = z.object({ + serverIp: z.string(), +}); + +type Schema = z.infer; + +interface Props { + children?: React.ReactNode; + serverId?: string; +} + +export const UpdateServerIp = ({ children, serverId }: Props) => { + const [isOpen, setIsOpen] = useState(false); + + const { data } = api.admin.one.useQuery(); + + const { mutateAsync, isLoading, error, isError } = + api.admin.update.useMutation(); + + const form = useForm({ + defaultValues: { + serverIp: data?.serverIp || "", + }, + resolver: zodResolver(schema), + }); + + useEffect(() => { + if (data) { + form.reset({ + serverIp: data.serverIp || "", + }); + } + }, [form, form.reset, data]); + + const utils = api.useUtils(); + + const onSubmit = async (data: Schema) => { + await mutateAsync({ + serverIp: data.serverIp, + }) + .then(async () => { + toast.success("Server IP Updated"); + await utils.admin.one.invalidate(); + setIsOpen(false); + }) + .catch(() => { + toast.error("Error to update the IP of the server"); + }); + }; + + return ( + + {children} + + + Update Server IP + Update the IP of the server + + {isError && {error?.message}} + +
+ + ( + + Server IP + + + +
+										
+									
+
+ )} + /> + + + + + + +
+
+ ); +}; diff --git a/apps/dokploy/components/dashboard/settings/web-server/update-server.tsx b/apps/dokploy/components/dashboard/settings/web-server/update-server.tsx index 165918652..757c77955 100644 --- a/apps/dokploy/components/dashboard/settings/web-server/update-server.tsx +++ b/apps/dokploy/components/dashboard/settings/web-server/update-server.tsx @@ -87,7 +87,7 @@ export const UpdateServer = () => { }} isLoading={isLoading} > - Check updates + Check Updates )}
diff --git a/apps/dokploy/server/api/routers/admin.ts b/apps/dokploy/server/api/routers/admin.ts index 42ce15bc0..d910f2230 100644 --- a/apps/dokploy/server/api/routers/admin.ts +++ b/apps/dokploy/server/api/routers/admin.ts @@ -4,6 +4,7 @@ import { apiCreateUserInvitation, apiFindOneToken, apiRemoveUser, + apiUpdateAdmin, users, } from "@/server/db/schema"; import { @@ -13,6 +14,7 @@ import { findUserById, getUserByToken, removeUserByAuthId, + updateAdmin, } from "@dokploy/server"; import { TRPCError } from "@trpc/server"; import { eq } from "drizzle-orm"; @@ -26,6 +28,12 @@ export const adminRouter = createTRPCRouter({ ...rest, }; }), + update: adminProcedure + .input(apiUpdateAdmin) + .mutation(async ({ input, ctx }) => { + const { authId } = await findAdminById(ctx.user.adminId); + return updateAdmin(authId, input); + }), createUserInvitation: adminProcedure .input(apiCreateUserInvitation) .mutation(async ({ input, ctx }) => { diff --git a/packages/server/src/db/schema/admin.ts b/packages/server/src/db/schema/admin.ts index cce611c24..222fb16c8 100644 --- a/packages/server/src/db/schema/admin.ts +++ b/packages/server/src/db/schema/admin.ts @@ -53,6 +53,8 @@ const createSchema = createInsertSchema(admins, { letsEncryptEmail: z.string().optional(), }); +export const apiUpdateAdmin = createSchema.partial(); + export const apiSaveSSHKey = createSchema .pick({ sshPrivateKey: true, From 2835c997e9424f94c137a7f36db5f6df5b71318b Mon Sep 17 00:00:00 2001 From: Krzysztof Durek <21038648+kdurek@users.noreply.github.com> Date: Sun, 17 Nov 2024 18:44:05 +0100 Subject: [PATCH 2/6] feat: update to use multi language --- .../dashboard/settings/servers/actions/show-dokploy-actions.tsx | 2 +- apps/dokploy/public/locales/en/settings.json | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/apps/dokploy/components/dashboard/settings/servers/actions/show-dokploy-actions.tsx b/apps/dokploy/components/dashboard/settings/servers/actions/show-dokploy-actions.tsx index 433928468..ee749244e 100644 --- a/apps/dokploy/components/dashboard/settings/servers/actions/show-dokploy-actions.tsx +++ b/apps/dokploy/components/dashboard/settings/servers/actions/show-dokploy-actions.tsx @@ -63,7 +63,7 @@ export const ShowDokployActions = () => { className="cursor-pointer" onSelect={(e) => e.preventDefault()} > - Update Server IP + {t("settings.server.webServer.updateServerIp")} diff --git a/apps/dokploy/public/locales/en/settings.json b/apps/dokploy/public/locales/en/settings.json index 594323f4a..2103ecc00 100644 --- a/apps/dokploy/public/locales/en/settings.json +++ b/apps/dokploy/public/locales/en/settings.json @@ -14,6 +14,7 @@ "settings.server.webServer.actions": "Actions", "settings.server.webServer.reload": "Reload", "settings.server.webServer.watchLogs": "Watch logs", + "settings.server.webServer.updateServerIp": "Update Server IP", "settings.server.webServer.server.label": "Server", "settings.server.webServer.traefik.label": "Traefik", "settings.server.webServer.traefik.modifyEnv": "Modify Env", From 3015d69adc916e8491f0c6a39d12111158f020b0 Mon Sep 17 00:00:00 2001 From: Krzysztof Durek <21038648+kdurek@users.noreply.github.com> Date: Sun, 17 Nov 2024 18:52:22 +0100 Subject: [PATCH 3/6] feat: add polish translation --- apps/dokploy/public/locales/pl/common.json | 1 + apps/dokploy/public/locales/pl/settings.json | 44 ++++++++++++++++++++ 2 files changed, 45 insertions(+) create mode 100644 apps/dokploy/public/locales/pl/common.json create mode 100644 apps/dokploy/public/locales/pl/settings.json diff --git a/apps/dokploy/public/locales/pl/common.json b/apps/dokploy/public/locales/pl/common.json new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/apps/dokploy/public/locales/pl/common.json @@ -0,0 +1 @@ +{} diff --git a/apps/dokploy/public/locales/pl/settings.json b/apps/dokploy/public/locales/pl/settings.json new file mode 100644 index 000000000..48531e69a --- /dev/null +++ b/apps/dokploy/public/locales/pl/settings.json @@ -0,0 +1,44 @@ +{ + "settings.common.save": "Zapisz", + "settings.server.domain.title": "Domena", + "settings.server.domain.description": "Dodaj domenę do aplikacji", + "settings.server.domain.form.domain": "Domena", + "settings.server.domain.form.letsEncryptEmail": "Email Let's Encrypt", + "settings.server.domain.form.certificate.label": "Certyfikat", + "settings.server.domain.form.certificate.placeholder": "Wybierz certyfikat", + "settings.server.domain.form.certificateOptions.none": "Brak", + "settings.server.domain.form.certificateOptions.letsencrypt": "Let's Encrypt (Domyślny)", + + "settings.server.webServer.title": "Serwer", + "settings.server.webServer.description": "Przeładuj lub wyczyść serwer", + "settings.server.webServer.actions": "Akcje", + "settings.server.webServer.reload": "Przeładuj", + "settings.server.webServer.watchLogs": "Obserwuj logi", + "settings.server.webServer.updateServerIp": "Zaktualizuj IP serwera", + "settings.server.webServer.server.label": "Serwer", + "settings.server.webServer.traefik.label": "Traefik", + "settings.server.webServer.traefik.modifyEnv": "Zmodyfikuj środowisko", + "settings.server.webServer.storage.label": "Przestrzeń", + "settings.server.webServer.storage.cleanUnusedImages": "Wyczyść nieużywane obrazy", + "settings.server.webServer.storage.cleanUnusedVolumes": "Wyczyść nieużywane wolumeny", + "settings.server.webServer.storage.cleanStoppedContainers": "Wyczyść zatrzymane kontenery", + "settings.server.webServer.storage.cleanDockerBuilder": "Wyczyść Docker Builder i System", + "settings.server.webServer.storage.cleanMonitoring": "Wyczyść monitorowanie", + "settings.server.webServer.storage.cleanAll": "Wyczyść wszystko", + + "settings.profile.title": "Konto", + "settings.profile.description": "Zmień szczegóły swojego profilu", + "settings.profile.email": "Email", + "settings.profile.password": "Hasło", + "settings.profile.avatar": "Avatar", + + "settings.appearance.title": "Wygląd", + "settings.appearance.description": "Dostosuj motyw swojego pulpitu", + "settings.appearance.theme": "Motyw", + "settings.appearance.themeDescription": "Wybierz motyw swojego pulpitu", + "settings.appearance.themes.light": "Jasny", + "settings.appearance.themes.dark": "Ciemny", + "settings.appearance.themes.system": "System", + "settings.appearance.language": "Język", + "settings.appearance.languageDescription": "Wybierz język swojego pulpitu" +} From 82367213ea99f027401823721eaaea5decd56f35 Mon Sep 17 00:00:00 2001 From: Krzysztof Durek <21038648+kdurek@users.noreply.github.com> Date: Sun, 17 Nov 2024 21:58:37 +0100 Subject: [PATCH 4/6] feat: add ability for setting current public IP in server IP update form --- .../settings/web-server/update-server-ip.tsx | 40 ++++++++++++++++++- apps/dokploy/server/api/routers/server.ts | 5 +++ 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/apps/dokploy/components/dashboard/settings/web-server/update-server-ip.tsx b/apps/dokploy/components/dashboard/settings/web-server/update-server-ip.tsx index 4834ef929..264b10ac5 100644 --- a/apps/dokploy/components/dashboard/settings/web-server/update-server-ip.tsx +++ b/apps/dokploy/components/dashboard/settings/web-server/update-server-ip.tsx @@ -19,8 +19,15 @@ import { FormMessage, } from "@/components/ui/form"; import { Input } from "@/components/ui/input"; +import { + Tooltip, + TooltipContent, + TooltipProvider, + TooltipTrigger, +} from "@/components/ui/tooltip"; import { api } from "@/utils/api"; import { zodResolver } from "@hookform/resolvers/zod"; +import { RefreshCw } from "lucide-react"; import { useEffect, useState } from "react"; import { useForm } from "react-hook-form"; import { toast } from "sonner"; @@ -41,6 +48,7 @@ export const UpdateServerIp = ({ children, serverId }: Props) => { const [isOpen, setIsOpen] = useState(false); const { data } = api.admin.one.useQuery(); + const { data: ip } = api.server.publicIp.useQuery(); const { mutateAsync, isLoading, error, isError } = api.admin.update.useMutation(); @@ -62,6 +70,11 @@ export const UpdateServerIp = ({ children, serverId }: Props) => { const utils = api.useUtils(); + const setCurrentIp = () => { + if (!ip) return; + form.setValue("serverIp", ip); + }; + const onSubmit = async (data: Schema) => { await mutateAsync({ serverIp: data.serverIp, @@ -97,8 +110,31 @@ export const UpdateServerIp = ({ children, serverId }: Props) => { render={({ field }) => ( Server IP - - + +
+ + + + + + + + +

Set current public IP

+
+
+
+
 										
diff --git a/apps/dokploy/server/api/routers/server.ts b/apps/dokploy/server/api/routers/server.ts
index 6caaa9c8b..97746131c 100644
--- a/apps/dokploy/server/api/routers/server.ts
+++ b/apps/dokploy/server/api/routers/server.ts
@@ -22,6 +22,7 @@ import {
 	findAdminById,
 	findServerById,
 	findServersByAdminId,
+	getPublicIpWithFallback,
 	haveActiveServices,
 	removeDeploymentsByServerId,
 	serverSetup,
@@ -181,4 +182,8 @@ export const serverRouter = createTRPCRouter({
 				throw error;
 			}
 		}),
+	publicIp: protectedProcedure.query(async ({ ctx }) => {
+		const ip = await getPublicIpWithFallback();
+		return ip;
+	}),
 });

From f138b0917fc18a3645bd2065daaa81826a6ec490 Mon Sep 17 00:00:00 2001
From: Krzysztof Durek <21038648+kdurek@users.noreply.github.com>
Date: Sun, 17 Nov 2024 22:05:52 +0100
Subject: [PATCH 5/6] feat: add Polish language support to appearance settings
 and locale configuration

---
 apps/dokploy/components/dashboard/settings/appearance-form.tsx | 3 ++-
 apps/dokploy/next-i18next.config.js                            | 2 +-
 apps/dokploy/pages/_app.tsx                                    | 2 +-
 apps/dokploy/utils/hooks/use-locale.ts                         | 2 +-
 4 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/apps/dokploy/components/dashboard/settings/appearance-form.tsx b/apps/dokploy/components/dashboard/settings/appearance-form.tsx
index a10b0d051..9bafbedab 100644
--- a/apps/dokploy/components/dashboard/settings/appearance-form.tsx
+++ b/apps/dokploy/components/dashboard/settings/appearance-form.tsx
@@ -37,7 +37,7 @@ const appearanceFormSchema = z.object({
 	theme: z.enum(["light", "dark", "system"], {
 		required_error: "Please select a theme.",
 	}),
-	language: z.enum(["en", "zh-Hans"], {
+	language: z.enum(["en", "pl", "zh-Hans"], {
 		required_error: "Please select a language.",
 	}),
 });
@@ -174,6 +174,7 @@ export function AppearanceForm() {
 											
 												{[
 													{ label: "English", value: "en" },
+													{ label: "Polski", value: "pl" },
 													{ label: "简体中文", value: "zh-Hans" },
 												].map((preset) => (
 													
diff --git a/apps/dokploy/next-i18next.config.js b/apps/dokploy/next-i18next.config.js
index 5c20bbea8..bac301cb4 100644
--- a/apps/dokploy/next-i18next.config.js
+++ b/apps/dokploy/next-i18next.config.js
@@ -2,7 +2,7 @@
 module.exports = {
 	i18n: {
 		defaultLocale: "en",
-		locales: ["en", "zh-Hans"],
+		locales: ["en", "pl", "zh-Hans"],
 		localeDetection: false,
 	},
 	fallbackLng: "en",
diff --git a/apps/dokploy/pages/_app.tsx b/apps/dokploy/pages/_app.tsx
index b5fcb1319..18cb3e7e6 100644
--- a/apps/dokploy/pages/_app.tsx
+++ b/apps/dokploy/pages/_app.tsx
@@ -71,7 +71,7 @@ export default api.withTRPC(
 		{
 			i18n: {
 				defaultLocale: "en",
-				locales: ["en", "zh-Hans"],
+				locales: ["en", "pl", "zh-Hans"],
 				localeDetection: false,
 			},
 			fallbackLng: "en",
diff --git a/apps/dokploy/utils/hooks/use-locale.ts b/apps/dokploy/utils/hooks/use-locale.ts
index f00e0df84..3c64f6438 100644
--- a/apps/dokploy/utils/hooks/use-locale.ts
+++ b/apps/dokploy/utils/hooks/use-locale.ts
@@ -1,6 +1,6 @@
 import Cookies from "js-cookie";
 
-const SUPPORTED_LOCALES = ["en", "zh-Hans"] as const;
+const SUPPORTED_LOCALES = ["en", "pl", "zh-Hans"] as const;
 
 type Locale = (typeof SUPPORTED_LOCALES)[number];
 

From 2307346ae35361e26f4adc51696e68781ece7426 Mon Sep 17 00:00:00 2001
From: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com>
Date: Sun, 17 Nov 2024 18:23:27 -0600
Subject: [PATCH 6/6] refactor: add validation to prevent run on cloud

---
 apps/dokploy/server/api/routers/admin.ts  | 6 ++++++
 apps/dokploy/server/api/routers/server.ts | 3 +++
 2 files changed, 9 insertions(+)

diff --git a/apps/dokploy/server/api/routers/admin.ts b/apps/dokploy/server/api/routers/admin.ts
index d910f2230..6029c7136 100644
--- a/apps/dokploy/server/api/routers/admin.ts
+++ b/apps/dokploy/server/api/routers/admin.ts
@@ -31,6 +31,12 @@ export const adminRouter = createTRPCRouter({
 	update: adminProcedure
 		.input(apiUpdateAdmin)
 		.mutation(async ({ input, ctx }) => {
+			if (ctx.user.rol === "user") {
+				throw new TRPCError({
+					code: "UNAUTHORIZED",
+					message: "You are not allowed to update this admin",
+				});
+			}
 			const { authId } = await findAdminById(ctx.user.adminId);
 			return updateAdmin(authId, input);
 		}),
diff --git a/apps/dokploy/server/api/routers/server.ts b/apps/dokploy/server/api/routers/server.ts
index 97746131c..0d4ef87f3 100644
--- a/apps/dokploy/server/api/routers/server.ts
+++ b/apps/dokploy/server/api/routers/server.ts
@@ -183,6 +183,9 @@ export const serverRouter = createTRPCRouter({
 			}
 		}),
 	publicIp: protectedProcedure.query(async ({ ctx }) => {
+		if (IS_CLOUD) {
+			return "";
+		}
 		const ip = await getPublicIpWithFallback();
 		return ip;
 	}),