From bfa4ebc801c1ade5bd218825beda80a3293ac6f3 Mon Sep 17 00:00:00 2001 From: Mauricio Siu Date: Sun, 5 Apr 2026 00:06:27 -0600 Subject: [PATCH] feat: add accessedServers permission handling and server access validation - Introduced `accessedServers` field in user permissions schema and member table. - Implemented server access validation across various API routers to ensure users can only access permitted servers. - Added a new query to fetch accessible server IDs based on user roles and licenses. - Updated UI components to support server selection in user permissions. --- .../settings/users/add-permissions.tsx | 86 + .../drizzle/0163_perfect_lethal_legion.sql | 1 + apps/dokploy/drizzle/meta/0163_snapshot.json | 8298 +++++++++++++++++ apps/dokploy/drizzle/meta/_journal.json | 7 + .../dokploy/server/api/routers/application.ts | 22 + apps/dokploy/server/api/routers/compose.ts | 22 + apps/dokploy/server/api/routers/libsql.ts | 12 + apps/dokploy/server/api/routers/mariadb.ts | 12 + apps/dokploy/server/api/routers/mongo.ts | 12 + apps/dokploy/server/api/routers/mysql.ts | 11 + apps/dokploy/server/api/routers/postgres.ts | 12 + apps/dokploy/server/api/routers/redis.ts | 12 + apps/dokploy/server/api/routers/server.ts | 45 +- apps/dokploy/server/api/routers/user.ts | 5 +- packages/server/src/db/schema/account.ts | 4 + packages/server/src/db/schema/user.ts | 1 + packages/server/src/services/server.ts | 38 +- 17 files changed, 8595 insertions(+), 5 deletions(-) create mode 100644 apps/dokploy/drizzle/0163_perfect_lethal_legion.sql create mode 100644 apps/dokploy/drizzle/meta/0163_snapshot.json diff --git a/apps/dokploy/components/dashboard/settings/users/add-permissions.tsx b/apps/dokploy/components/dashboard/settings/users/add-permissions.tsx index ee2d1d44c..01efdd788 100644 --- a/apps/dokploy/components/dashboard/settings/users/add-permissions.tsx +++ b/apps/dokploy/components/dashboard/settings/users/add-permissions.tsx @@ -172,6 +172,7 @@ const addPermissions = z.object({ accessedEnvironments: z.array(z.string()).optional(), accessedServices: z.array(z.string()).optional(), accessedGitProviders: z.array(z.string()).optional(), + accessedServers: z.array(z.string()).optional(), canCreateProjects: z.boolean().optional().default(false), canCreateServices: z.boolean().optional().default(false), canDeleteProjects: z.boolean().optional().default(false), @@ -208,6 +209,13 @@ export const AddUserPermissions = ({ userId, role }: Props) => { }, ); + const { data: servers } = api.server.allForPermissions.useQuery( + undefined, + { + enabled: isOpen && !!haveValidLicense, + }, + ); + const { data, refetch } = api.user.one.useQuery( { userId, @@ -226,6 +234,7 @@ export const AddUserPermissions = ({ userId, role }: Props) => { accessedEnvironments: [], accessedServices: [], accessedGitProviders: [], + accessedServers: [], canDeleteEnvironments: false, canCreateProjects: false, canCreateServices: false, @@ -248,6 +257,7 @@ export const AddUserPermissions = ({ userId, role }: Props) => { accessedEnvironments: data.accessedEnvironments || [], accessedServices: data.accessedServices || [], accessedGitProviders: data.accessedGitProviders || [], + accessedServers: data.accessedServers || [], canCreateProjects: data.canCreateProjects, canCreateServices: data.canCreateServices, canDeleteProjects: data.canDeleteProjects, @@ -276,6 +286,7 @@ export const AddUserPermissions = ({ userId, role }: Props) => { accessedEnvironments: data.accessedEnvironments || [], accessedServices: data.accessedServices || [], accessedGitProviders: data.accessedGitProviders || [], + accessedServers: data.accessedServers || [], canAccessToDocker: data.canAccessToDocker, canAccessToAPI: data.canAccessToAPI, canAccessToSSHKeys: data.canAccessToSSHKeys, @@ -956,6 +967,81 @@ export const AddUserPermissions = ({ userId, role }: Props) => { /> )} + {haveValidLicense ? ( + ( + +
+ Servers + + Select the Servers that the user can access + +
+ {servers?.length === 0 && ( +

+ No servers found +

+ )} +
+ {servers?.map((s) => ( + ( + + + { + if (checked) { + field.onChange([ + ...(field.value || []), + s.serverId, + ]); + } else { + field.onChange( + field.value?.filter( + (v) => v !== s.serverId, + ), + ); + } + }} + /> + +
+ + {s.name} + + + ({s.ipAddress}) + + + {s.serverType} + +
+
+ )} + /> + ))} +
+ +
+ )} + /> + ) : ( +
+ +
+ )}