import { containerRestart, findServerById, getConfig, getContainers, getContainersByAppLabel, getContainersByAppNameMatch, getServiceContainersByAppName, getStackContainersByAppName, } from "@dokploy/server"; import { TRPCError } from "@trpc/server"; import { z } from "zod"; import { audit } from "@/server/api/utils/audit"; import { createTRPCRouter, withPermission } from "../trpc"; export const containerIdRegex = /^[a-zA-Z0-9.\-_]+$/; export const dockerRouter = createTRPCRouter({ getContainers: withPermission("docker", "read") .input( z.object({ serverId: z.string().optional(), }), ) .query(async ({ input, ctx }) => { if (input.serverId) { const server = await findServerById(input.serverId); if (server.organizationId !== ctx.session?.activeOrganizationId) { throw new TRPCError({ code: "UNAUTHORIZED" }); } } return await getContainers(input.serverId); }), restartContainer: withPermission("docker", "read") .input( z.object({ containerId: z .string() .min(1) .regex(containerIdRegex, "Invalid container id."), }), ) .mutation(async ({ input, ctx }) => { const result = await containerRestart(input.containerId); await audit(ctx, { action: "start", resourceType: "docker", resourceId: input.containerId, resourceName: input.containerId, }); return result; }), getConfig: withPermission("docker", "read") .input( z.object({ containerId: z .string() .min(1) .regex(containerIdRegex, "Invalid container id."), serverId: z.string().optional(), }), ) .query(async ({ input, ctx }) => { if (input.serverId) { const server = await findServerById(input.serverId); if (server.organizationId !== ctx.session?.activeOrganizationId) { throw new TRPCError({ code: "UNAUTHORIZED" }); } } return await getConfig(input.containerId, input.serverId); }), getContainersByAppNameMatch: withPermission("service", "read") .input( z.object({ appType: z.enum(["stack", "docker-compose"]).optional(), appName: z.string().min(1).regex(containerIdRegex, "Invalid app name."), serverId: z.string().optional(), }), ) .query(async ({ input, ctx }) => { if (input.serverId) { const server = await findServerById(input.serverId); if (server.organizationId !== ctx.session?.activeOrganizationId) { throw new TRPCError({ code: "UNAUTHORIZED" }); } } return await getContainersByAppNameMatch( input.appName, input.appType, input.serverId, ); }), getContainersByAppLabel: withPermission("docker", "read") .input( z.object({ appName: z.string().min(1).regex(containerIdRegex, "Invalid app name."), serverId: z.string().optional(), type: z.enum(["standalone", "swarm"]), }), ) .query(async ({ input, ctx }) => { if (input.serverId) { const server = await findServerById(input.serverId); if (server.organizationId !== ctx.session?.activeOrganizationId) { throw new TRPCError({ code: "UNAUTHORIZED" }); } } return await getContainersByAppLabel( input.appName, input.type, input.serverId, ); }), getStackContainersByAppName: withPermission("docker", "read") .input( z.object({ appName: z.string().min(1).regex(containerIdRegex, "Invalid app name."), serverId: z.string().optional(), }), ) .query(async ({ input, ctx }) => { if (input.serverId) { const server = await findServerById(input.serverId); if (server.organizationId !== ctx.session?.activeOrganizationId) { throw new TRPCError({ code: "UNAUTHORIZED" }); } } return await getStackContainersByAppName(input.appName, input.serverId); }), getServiceContainersByAppName: withPermission("docker", "read") .input( z.object({ appName: z.string().min(1).regex(containerIdRegex, "Invalid app name."), serverId: z.string().optional(), }), ) .query(async ({ input, ctx }) => { if (input.serverId) { const server = await findServerById(input.serverId); if (server.organizationId !== ctx.session?.activeOrganizationId) { throw new TRPCError({ code: "UNAUTHORIZED" }); } } return await getServiceContainersByAppName(input.appName, input.serverId); }), });