From d330b164e5dfa8b242065584cc2e4ba8173a5b99 Mon Sep 17 00:00:00 2001 From: Mauricio Siu Date: Sun, 5 Jul 2026 16:16:53 -0600 Subject: [PATCH] fix(deployment): resolve schedule to its service before permission check in allByType Members with access to a schedule's application/compose got a 401 on deployment.allByType because it passed the scheduleId straight into checkServicePermissionAndAccess, which expects a service id. --- apps/dokploy/server/api/routers/deployment.ts | 25 ++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/apps/dokploy/server/api/routers/deployment.ts b/apps/dokploy/server/api/routers/deployment.ts index 0d7a913719..1df7840632 100644 --- a/apps/dokploy/server/api/routers/deployment.ts +++ b/apps/dokploy/server/api/routers/deployment.ts @@ -6,6 +6,7 @@ import { findAllDeploymentsByServerId, findAllDeploymentsCentralized, findDeploymentById, + findScheduleById, IS_CLOUD, removeDeployment, resolveServicePath, @@ -126,9 +127,27 @@ export const deploymentRouter = createTRPCRouter({ allByType: protectedProcedure .input(apiFindAllByType) .query(async ({ input, ctx }) => { - await checkServicePermissionAndAccess(ctx, input.id, { - deployment: ["read"], - }); + if (input.type === "schedule") { + const schedule = await findScheduleById(input.id); + const serviceId = schedule.applicationId || schedule.composeId; + if (serviceId) { + await checkServicePermissionAndAccess(ctx, serviceId, { + deployment: ["read"], + }); + } else if (schedule.serverId) { + const targetServer = await findServerById(schedule.serverId); + if (targetServer.organizationId !== ctx.session.activeOrganizationId) { + throw new TRPCError({ + code: "UNAUTHORIZED", + message: "You don't have access to this schedule.", + }); + } + } + } else { + await checkServicePermissionAndAccess(ctx, input.id, { + deployment: ["read"], + }); + } const deploymentsList = await db.query.deployments.findMany({ where: eq(deployments[`${input.type}Id`], input.id), orderBy: desc(deployments.createdAt),