diff --git a/apps/dokploy/server/api/routers/deployment.ts b/apps/dokploy/server/api/routers/deployment.ts index d12e430fc..22e750c78 100644 --- a/apps/dokploy/server/api/routers/deployment.ts +++ b/apps/dokploy/server/api/routers/deployment.ts @@ -7,24 +7,49 @@ import { findAllDeploymentsByApplicationId, findAllDeploymentsByComposeId, findAllDeploymentsByServerId, + findApplicationById, + findComposeById, + findServerById, } from "@dokploy/builders"; import { createTRPCRouter, protectedProcedure } from "../trpc"; +import { TRPCError } from "@trpc/server"; export const deploymentRouter = createTRPCRouter({ all: protectedProcedure .input(apiFindAllByApplication) - .query(async ({ input }) => { + .query(async ({ input, ctx }) => { + const application = await findApplicationById(input.applicationId); + if (application.project.adminId !== ctx.user.adminId) { + throw new TRPCError({ + code: "UNAUTHORIZED", + message: "You are not authorized to access this application", + }); + } return await findAllDeploymentsByApplicationId(input.applicationId); }), allByCompose: protectedProcedure .input(apiFindAllByCompose) - .query(async ({ input }) => { + .query(async ({ input, ctx }) => { + const compose = await findComposeById(input.composeId); + if (compose.project.adminId !== ctx.user.adminId) { + throw new TRPCError({ + code: "UNAUTHORIZED", + message: "You are not authorized to access this compose", + }); + } return await findAllDeploymentsByComposeId(input.composeId); }), allByServer: protectedProcedure .input(apiFindAllByServer) - .query(async ({ input }) => { + .query(async ({ input, ctx }) => { + const server = await findServerById(input.serverId); + if (server.adminId !== ctx.user.adminId) { + throw new TRPCError({ + code: "UNAUTHORIZED", + message: "You are not authorized to access this server", + }); + } return await findAllDeploymentsByServerId(input.serverId); }), }); diff --git a/apps/dokploy/server/api/routers/domain.ts b/apps/dokploy/server/api/routers/domain.ts index 2f044aca8..72a7a2044 100644 --- a/apps/dokploy/server/api/routers/domain.ts +++ b/apps/dokploy/server/api/routers/domain.ts @@ -19,13 +19,31 @@ import { generateTraefikMeDomain, removeDomainById, updateDomainById, + findComposeById, } from "@dokploy/builders"; export const domainRouter = createTRPCRouter({ create: protectedProcedure .input(apiCreateDomain) - .mutation(async ({ input }) => { + .mutation(async ({ input, ctx }) => { try { + if (input.domainType === "compose" && input.composeId) { + const compose = await findComposeById(input.composeId); + if (compose.project.adminId !== ctx.user.adminId) { + throw new TRPCError({ + code: "UNAUTHORIZED", + message: "You are not authorized to access this compose", + }); + } + } else if (input.domainType === "application" && input.applicationId) { + const application = await findApplicationById(input.applicationId); + if (application.project.adminId !== ctx.user.adminId) { + throw new TRPCError({ + code: "UNAUTHORIZED", + message: "You are not authorized to access this application", + }); + } + } return await createDomain(input); } catch (error) { throw new TRPCError({ @@ -37,12 +55,26 @@ export const domainRouter = createTRPCRouter({ }), byApplicationId: protectedProcedure .input(apiFindOneApplication) - .query(async ({ input }) => { + .query(async ({ input, ctx }) => { + const application = await findApplicationById(input.applicationId); + if (application.project.adminId !== ctx.user.adminId) { + throw new TRPCError({ + code: "UNAUTHORIZED", + message: "You are not authorized to access this application", + }); + } return await findDomainsByApplicationId(input.applicationId); }), byComposeId: protectedProcedure .input(apiFindCompose) - .query(async ({ input }) => { + .query(async ({ input, ctx }) => { + const compose = await findComposeById(input.composeId); + if (compose.project.adminId !== ctx.user.adminId) { + throw new TRPCError({ + code: "UNAUTHORIZED", + message: "You are not authorized to access this compose", + }); + } return await findDomainsByComposeId(input.composeId); }), generateDomain: protectedProcedure @@ -57,7 +89,26 @@ export const domainRouter = createTRPCRouter({ update: protectedProcedure .input(apiUpdateDomain) - .mutation(async ({ input }) => { + .mutation(async ({ input, ctx }) => { + const currentDomain = await findDomainById(input.domainId); + + if (currentDomain.applicationId) { + const newApp = await findApplicationById(currentDomain.applicationId); + if (newApp.project.adminId !== ctx.user.adminId) { + throw new TRPCError({ + code: "UNAUTHORIZED", + message: "You are not authorized to access this application", + }); + } + } else if (currentDomain.composeId) { + const newCompose = await findComposeById(currentDomain.composeId); + if (newCompose.project.adminId !== ctx.user.adminId) { + throw new TRPCError({ + code: "UNAUTHORIZED", + message: "You are not authorized to access this compose", + }); + } + } const result = await updateDomainById(input.domainId, input); const domain = await findDomainById(input.domainId); if (domain.applicationId) { @@ -66,13 +117,48 @@ export const domainRouter = createTRPCRouter({ } return result; }), - one: protectedProcedure.input(apiFindDomain).query(async ({ input }) => { + one: protectedProcedure.input(apiFindDomain).query(async ({ input, ctx }) => { + const domain = await findDomainById(input.domainId); + if (domain.applicationId) { + const application = await findApplicationById(domain.applicationId); + if (application.project.adminId !== ctx.user.adminId) { + throw new TRPCError({ + code: "UNAUTHORIZED", + message: "You are not authorized to access this application", + }); + } + } else if (domain.composeId) { + const compose = await findComposeById(domain.composeId); + if (compose.project.adminId !== ctx.user.adminId) { + throw new TRPCError({ + code: "UNAUTHORIZED", + message: "You are not authorized to access this compose", + }); + } + } return await findDomainById(input.domainId); }), delete: protectedProcedure .input(apiFindDomain) - .mutation(async ({ input }) => { + .mutation(async ({ input, ctx }) => { const domain = await findDomainById(input.domainId); + if (domain.applicationId) { + const application = await findApplicationById(domain.applicationId); + if (application.project.adminId !== ctx.user.adminId) { + throw new TRPCError({ + code: "UNAUTHORIZED", + message: "You are not authorized to access this application", + }); + } + } else if (domain.composeId) { + const compose = await findComposeById(domain.composeId); + if (compose.project.adminId !== ctx.user.adminId) { + throw new TRPCError({ + code: "UNAUTHORIZED", + message: "You are not authorized to access this compose", + }); + } + } const result = await removeDomainById(input.domainId); if (domain.applicationId) { diff --git a/apps/dokploy/server/api/routers/redirects.ts b/apps/dokploy/server/api/routers/redirects.ts index 7bd57fe52..5c89a41c8 100644 --- a/apps/dokploy/server/api/routers/redirects.ts +++ b/apps/dokploy/server/api/routers/redirects.ts @@ -5,29 +5,64 @@ import { } from "@/server/db/schema"; import { createRedirect, + findApplicationById, findRedirectById, removeRedirectById, updateRedirectById, } from "@dokploy/builders"; import { createTRPCRouter, protectedProcedure } from "../trpc"; +import { TRPCError } from "@trpc/server"; export const redirectsRouter = createTRPCRouter({ create: protectedProcedure .input(apiCreateRedirect) - .mutation(async ({ input }) => { + .mutation(async ({ input, ctx }) => { + const application = await findApplicationById(input.applicationId); + if (application.project.adminId !== ctx.user.adminId) { + throw new TRPCError({ + code: "UNAUTHORIZED", + message: "You are not authorized to access this application", + }); + } return await createRedirect(input); }), - one: protectedProcedure.input(apiFindOneRedirect).query(async ({ input }) => { - return findRedirectById(input.redirectId); - }), + one: protectedProcedure + .input(apiFindOneRedirect) + .query(async ({ input, ctx }) => { + const redirect = await findRedirectById(input.redirectId); + const application = await findApplicationById(redirect.applicationId); + if (application.project.adminId !== ctx.user.adminId) { + throw new TRPCError({ + code: "UNAUTHORIZED", + message: "You are not authorized to access this application", + }); + } + return findRedirectById(input.redirectId); + }), delete: protectedProcedure .input(apiFindOneRedirect) - .mutation(async ({ input }) => { + .mutation(async ({ input, ctx }) => { + const redirect = await findRedirectById(input.redirectId); + const application = await findApplicationById(redirect.applicationId); + if (application.project.adminId !== ctx.user.adminId) { + throw new TRPCError({ + code: "UNAUTHORIZED", + message: "You are not authorized to access this application", + }); + } return removeRedirectById(input.redirectId); }), update: protectedProcedure .input(apiUpdateRedirect) - .mutation(async ({ input }) => { + .mutation(async ({ input, ctx }) => { + const redirect = await findRedirectById(input.redirectId); + const application = await findApplicationById(redirect.applicationId); + if (application.project.adminId !== ctx.user.adminId) { + throw new TRPCError({ + code: "UNAUTHORIZED", + message: "You are not authorized to access this application", + }); + } return updateRedirectById(input.redirectId, input); }), }); diff --git a/apps/dokploy/server/api/routers/security.ts b/apps/dokploy/server/api/routers/security.ts index 9b94c9475..7a3e059c4 100644 --- a/apps/dokploy/server/api/routers/security.ts +++ b/apps/dokploy/server/api/routers/security.ts @@ -6,28 +6,63 @@ import { import { createSecurity, deleteSecurityById, + findApplicationById, findSecurityById, updateSecurityById, } from "@dokploy/builders"; import { createTRPCRouter, protectedProcedure } from "../trpc"; +import { TRPCError } from "@trpc/server"; export const securityRouter = createTRPCRouter({ create: protectedProcedure .input(apiCreateSecurity) - .mutation(async ({ input }) => { + .mutation(async ({ input, ctx }) => { + const application = await findApplicationById(input.applicationId); + if (application.project.adminId !== ctx.user.adminId) { + throw new TRPCError({ + code: "UNAUTHORIZED", + message: "You are not authorized to access this application", + }); + } return await createSecurity(input); }), - one: protectedProcedure.input(apiFindOneSecurity).query(async ({ input }) => { - return await findSecurityById(input.securityId); - }), + one: protectedProcedure + .input(apiFindOneSecurity) + .query(async ({ input, ctx }) => { + const security = await findSecurityById(input.securityId); + const application = await findApplicationById(security.applicationId); + if (application.project.adminId !== ctx.user.adminId) { + throw new TRPCError({ + code: "UNAUTHORIZED", + message: "You are not authorized to access this application", + }); + } + return await findSecurityById(input.securityId); + }), delete: protectedProcedure .input(apiFindOneSecurity) - .mutation(async ({ input }) => { + .mutation(async ({ input, ctx }) => { + const security = await findSecurityById(input.securityId); + const application = await findApplicationById(security.applicationId); + if (application.project.adminId !== ctx.user.adminId) { + throw new TRPCError({ + code: "UNAUTHORIZED", + message: "You are not authorized to access this application", + }); + } return await deleteSecurityById(input.securityId); }), update: protectedProcedure .input(apiUpdateSecurity) - .mutation(async ({ input }) => { + .mutation(async ({ input, ctx }) => { + const security = await findSecurityById(input.securityId); + const application = await findApplicationById(security.applicationId); + if (application.project.adminId !== ctx.user.adminId) { + throw new TRPCError({ + code: "UNAUTHORIZED", + message: "You are not authorized to access this application", + }); + } return await updateSecurityById(input.securityId, input); }), }); diff --git a/apps/dokploy/server/api/routers/settings.ts b/apps/dokploy/server/api/routers/settings.ts index 5e82d96e6..bed8deb53 100644 --- a/apps/dokploy/server/api/routers/settings.ts +++ b/apps/dokploy/server/api/routers/settings.ts @@ -60,6 +60,9 @@ import { adminProcedure, createTRPCRouter, protectedProcedure } from "../trpc"; export const settingsRouter = createTRPCRouter({ reloadServer: adminProcedure.mutation(async () => { + if (IS_CLOUD) { + return true; + } const { stdout } = await execAsync( "docker service inspect dokploy --format '{{.ID}}'", ); @@ -73,7 +76,7 @@ export const settingsRouter = createTRPCRouter({ if (input?.serverId) { await stopServiceRemote(input.serverId, "dokploy-traefik"); await startServiceRemote(input.serverId, "dokploy-traefik"); - } else { + } else if (!IS_CLOUD) { await stopService("dokploy-traefik"); await startService("dokploy-traefik"); } @@ -135,6 +138,9 @@ export const settingsRouter = createTRPCRouter({ return true; }), cleanMonitoring: adminProcedure.mutation(async () => { + if (IS_CLOUD) { + return true; + } const { MONITORING_PATH } = paths(); await recreateDirectory(MONITORING_PATH); return true; @@ -142,6 +148,9 @@ export const settingsRouter = createTRPCRouter({ saveSSHPrivateKey: adminProcedure .input(apiSaveSSHKey) .mutation(async ({ input, ctx }) => { + if (IS_CLOUD) { + return true; + } await updateAdmin(ctx.user.authId, { sshPrivateKey: input.sshPrivateKey, }); @@ -151,6 +160,9 @@ export const settingsRouter = createTRPCRouter({ assignDomainServer: adminProcedure .input(apiAssignDomain) .mutation(async ({ ctx, input }) => { + if (IS_CLOUD) { + return true; + } const admin = await updateAdmin(ctx.user.authId, { host: input.host, letsEncryptEmail: input.letsEncryptEmail, @@ -169,6 +181,9 @@ export const settingsRouter = createTRPCRouter({ return admin; }), cleanSSHPrivateKey: adminProcedure.mutation(async ({ ctx }) => { + if (IS_CLOUD) { + return true; + } await updateAdmin(ctx.user.authId, { sshPrivateKey: null, }); @@ -194,7 +209,7 @@ export const settingsRouter = createTRPCRouter({ await sendDockerCleanupNotifications(); }); } - } else { + } else if (!IS_CLOUD) { await updateAdmin(ctx.user.authId, { enableDockerCleanup: input.enableDockerCleanup, }); @@ -220,6 +235,9 @@ export const settingsRouter = createTRPCRouter({ }), readTraefikConfig: adminProcedure.query(() => { + if (IS_CLOUD) { + return true; + } const traefikConfig = readMainConfig(); return traefikConfig; }), @@ -227,22 +245,34 @@ export const settingsRouter = createTRPCRouter({ updateTraefikConfig: adminProcedure .input(apiTraefikConfig) .mutation(async ({ input }) => { + if (IS_CLOUD) { + return true; + } writeMainConfig(input.traefikConfig); return true; }), readWebServerTraefikConfig: adminProcedure.query(() => { + if (IS_CLOUD) { + return true; + } const traefikConfig = readConfig("dokploy"); return traefikConfig; }), updateWebServerTraefikConfig: adminProcedure .input(apiTraefikConfig) .mutation(async ({ input }) => { + if (IS_CLOUD) { + return true; + } writeConfig("dokploy", input.traefikConfig); return true; }), readMiddlewareTraefikConfig: adminProcedure.query(() => { + if (IS_CLOUD) { + return true; + } const traefikConfig = readConfig("middlewares"); return traefikConfig; }), @@ -250,14 +280,23 @@ export const settingsRouter = createTRPCRouter({ updateMiddlewareTraefikConfig: adminProcedure .input(apiTraefikConfig) .mutation(async ({ input }) => { + if (IS_CLOUD) { + return true; + } writeConfig("middlewares", input.traefikConfig); return true; }), checkAndUpdateImage: adminProcedure.mutation(async () => { + if (IS_CLOUD) { + return true; + } return await pullLatestRelease(); }), updateServer: adminProcedure.mutation(async () => { + if (IS_CLOUD) { + return true; + } await spawnAsync("docker", [ "service", "update", @@ -322,6 +361,9 @@ export const settingsRouter = createTRPCRouter({ return readConfigInPath(input.path, input.serverId); }), getIp: protectedProcedure.query(async () => { + if (IS_CLOUD) { + return true; + } const admin = await findAdmin(); return admin.serverIp; }), @@ -387,8 +429,10 @@ export const settingsRouter = createTRPCRouter({ const result = await execAsyncRemote(input.serverId, command); return result.stdout.trim(); } - const result = await execAsync(command); - return result.stdout.trim(); + if (!IS_CLOUD) { + const result = await execAsync(command); + return result.stdout.trim(); + } }), writeTraefikEnv: adminProcedure @@ -439,6 +483,9 @@ export const settingsRouter = createTRPCRouter({ }) .input(apiReadStatsLogs) .query(({ input }) => { + if (IS_CLOUD) { + return true; + } const rawConfig = readMonitoringConfig(); const parsedConfig = parseRawConfig( rawConfig as string, @@ -451,11 +498,17 @@ export const settingsRouter = createTRPCRouter({ return parsedConfig; }), readStats: adminProcedure.query(() => { + if (IS_CLOUD) { + return true; + } const rawConfig = readMonitoringConfig(); const processedLogs = processLogs(rawConfig as string); return processedLogs || []; }), getLogRotateStatus: adminProcedure.query(async () => { + if (IS_CLOUD) { + return true; + } return await logRotationManager.getStatus(); }), toggleLogRotate: adminProcedure @@ -465,6 +518,9 @@ export const settingsRouter = createTRPCRouter({ }), ) .mutation(async ({ input }) => { + if (IS_CLOUD) { + return true; + } if (input.enable) { await logRotationManager.activate(); } else { @@ -474,6 +530,9 @@ export const settingsRouter = createTRPCRouter({ return true; }), haveActivateRequests: adminProcedure.query(async () => { + if (IS_CLOUD) { + return true; + } const config = readMainConfig(); if (!config) return false; @@ -492,6 +551,9 @@ export const settingsRouter = createTRPCRouter({ }), ) .mutation(async ({ input }) => { + if (IS_CLOUD) { + return true; + } const mainConfig = readMainConfig(); if (!mainConfig) return false;