From 4732b38d5a3b3d6950cddeda800108e83cb8860f Mon Sep 17 00:00:00 2001 From: Mauricio Siu Date: Tue, 11 Aug 2026 02:04:09 -0600 Subject: [PATCH] refactor: align cluster/swarm read queries with docker.read, gate node actions by server permissions --- .../settings/cluster/nodes/show-nodes.tsx | 56 ++++++++++--------- apps/dokploy/server/api/routers/cluster.ts | 2 +- apps/dokploy/server/api/routers/swarm.ts | 10 ++-- 3 files changed, 35 insertions(+), 33 deletions(-) diff --git a/apps/dokploy/components/dashboard/settings/cluster/nodes/show-nodes.tsx b/apps/dokploy/components/dashboard/settings/cluster/nodes/show-nodes.tsx index 1991d57d2..ef036507a 100644 --- a/apps/dokploy/components/dashboard/settings/cluster/nodes/show-nodes.tsx +++ b/apps/dokploy/components/dashboard/settings/cluster/nodes/show-nodes.tsx @@ -52,6 +52,7 @@ export const ShowNodes = ({ serverId }: Props) => { serverId, }); const { data: registry } = api.registry.all.useQuery(); + const { data: permissions } = api.user.getPermissions.useQuery(); const { mutateAsync: deleteNode } = api.cluster.removeWorker.useMutation(); @@ -68,7 +69,7 @@ export const ShowNodes = ({ serverId }: Props) => { Add nodes to your cluster - {haveAtLeastOneRegistry && ( + {haveAtLeastOneRegistry && permissions?.server.create && (
@@ -144,34 +145,35 @@ export const ShowNodes = ({ serverId }: Props) => { Actions - {!node?.ManagerStatus?.Leader && ( - { - await deleteNode({ - nodeId: node.ID, - serverId, - }) - .then(() => { - refetch(); - toast.success( - "Node deleted successfully", - ); + {!node?.ManagerStatus?.Leader && + permissions?.server.delete && ( + { + await deleteNode({ + nodeId: node.ID, + serverId, }) - .catch(() => { - toast.error("Error deleting node"); - }); - }} - > - e.preventDefault()} + .then(() => { + refetch(); + toast.success( + "Node deleted successfully", + ); + }) + .catch(() => { + toast.error("Error deleting node"); + }); + }} > - Delete - - - )} + e.preventDefault()} + > + Delete + + + )} diff --git a/apps/dokploy/server/api/routers/cluster.ts b/apps/dokploy/server/api/routers/cluster.ts index ff0bc4de6..f121c62ea 100644 --- a/apps/dokploy/server/api/routers/cluster.ts +++ b/apps/dokploy/server/api/routers/cluster.ts @@ -13,7 +13,7 @@ import { getLocalServerIp } from "@/server/wss/terminal"; import { createTRPCRouter, withPermission } from "../trpc"; export const clusterRouter = createTRPCRouter({ - getNodes: withPermission("server", "read") + getNodes: withPermission("docker", "read") .input( z.object({ serverId: z.string().optional(), diff --git a/apps/dokploy/server/api/routers/swarm.ts b/apps/dokploy/server/api/routers/swarm.ts index 483bccf3e..771c52adf 100644 --- a/apps/dokploy/server/api/routers/swarm.ts +++ b/apps/dokploy/server/api/routers/swarm.ts @@ -12,7 +12,7 @@ import { createTRPCRouter, withPermission } from "../trpc"; import { containerIdRegex } from "./docker"; export const swarmRouter = createTRPCRouter({ - getNodes: withPermission("server", "read") + getNodes: withPermission("docker", "read") .input( z.object({ serverId: z.string().optional(), @@ -30,7 +30,7 @@ export const swarmRouter = createTRPCRouter({ } return await getSwarmNodes(input.serverId); }), - getNodeInfo: withPermission("server", "read") + getNodeInfo: withPermission("docker", "read") .input(z.object({ nodeId: z.string(), serverId: z.string().optional() })) .query(async ({ input, ctx }) => { if (input.serverId) { @@ -44,7 +44,7 @@ export const swarmRouter = createTRPCRouter({ } return await getNodeInfo(input.nodeId, input.serverId); }), - getNodeApps: withPermission("server", "read") + getNodeApps: withPermission("docker", "read") .input( z.object({ serverId: z.string().optional(), @@ -62,7 +62,7 @@ export const swarmRouter = createTRPCRouter({ } return getNodeApplications(input.serverId); }), - getAppInfos: withPermission("server", "read") + getAppInfos: withPermission("docker", "read") .meta({ openapi: { path: "/drop-deployment", @@ -93,7 +93,7 @@ export const swarmRouter = createTRPCRouter({ } return await getApplicationInfo(input.appName, input.serverId); }), - getContainerStats: withPermission("server", "read") + getContainerStats: withPermission("docker", "read") .input( z.object({ serverId: z.string().optional(),