Files
dokploy/apps/dokploy/server/api/routers/preview-deployment.ts
Mauricio Siu 8127dc4536 feat: add comprehensive permission tests and enhance permission checks in components
- Introduced new test files for permission checks, including `check-permission.test.ts`, `enterprise-only-resources.test.ts`, `resolve-permissions.test.ts`, and `service-access.test.ts`.
- Implemented permission checks in various components to ensure actions are gated by user permissions, including `ShowTraefikConfig`, `UpdateTraefikConfig`, `ShowVolumes`, `ShowDomains`, and others.
- Enhanced the logic for displaying UI elements based on user permissions, ensuring that only authorized users can access or modify resources.
2026-03-15 16:42:48 -06:00

119 lines
3.4 KiB
TypeScript

import {
findApplicationById,
findPreviewDeploymentById,
findPreviewDeploymentsByApplicationId,
IS_CLOUD,
removePreviewDeployment,
} from "@dokploy/server";
import { checkServicePermissionAndAccess } from "@dokploy/server/services/permission";
import { z } from "zod";
import { audit } from "@/server/api/utils/audit";
import { apiFindAllByApplication } from "@/server/db/schema";
import type { DeploymentJob } from "@/server/queues/queue-types";
import { myQueue } from "@/server/queues/queueSetup";
import { deploy } from "@/server/utils/deploy";
import { createTRPCRouter, protectedProcedure } from "../trpc";
export const previewDeploymentRouter = createTRPCRouter({
all: protectedProcedure
.input(apiFindAllByApplication)
.query(async ({ input, ctx }) => {
await checkServicePermissionAndAccess(ctx, input.applicationId, {
deployment: ["read"],
});
return await findPreviewDeploymentsByApplicationId(input.applicationId);
}),
one: protectedProcedure
.input(z.object({ previewDeploymentId: z.string() }))
.query(async ({ input, ctx }) => {
const previewDeployment = await findPreviewDeploymentById(
input.previewDeploymentId,
);
await checkServicePermissionAndAccess(
ctx,
previewDeployment.applicationId,
{ deployment: ["read"] },
);
return previewDeployment;
}),
delete: protectedProcedure
.input(z.object({ previewDeploymentId: z.string() }))
.mutation(async ({ input, ctx }) => {
const previewDeployment = await findPreviewDeploymentById(
input.previewDeploymentId,
);
await checkServicePermissionAndAccess(
ctx,
previewDeployment.applicationId,
{ deployment: ["cancel"] },
);
await removePreviewDeployment(input.previewDeploymentId);
await audit(ctx, {
action: "delete",
resourceType: "previewDeployment",
resourceId: input.previewDeploymentId,
});
return true;
}),
redeploy: protectedProcedure
.input(
z.object({
previewDeploymentId: z.string(),
title: z.string().optional(),
description: z.string().optional(),
}),
)
.mutation(async ({ input, ctx }) => {
const previewDeployment = await findPreviewDeploymentById(
input.previewDeploymentId,
);
await checkServicePermissionAndAccess(
ctx,
previewDeployment.applicationId,
{ deployment: ["create"] },
);
const application = await findApplicationById(
previewDeployment.applicationId,
);
const jobData: DeploymentJob = {
applicationId: previewDeployment.applicationId,
titleLog: input.title || "Rebuild Preview Deployment",
descriptionLog: input.description || "",
type: "redeploy",
applicationType: "application-preview",
previewDeploymentId: input.previewDeploymentId,
server: !!application.serverId,
};
if (IS_CLOUD && application.serverId) {
jobData.serverId = application.serverId;
deploy(jobData).catch((error) => {
console.error("Background deployment failed:", error);
});
await audit(ctx, {
action: "redeploy",
resourceType: "previewDeployment",
resourceId: input.previewDeploymentId,
});
return true;
}
await myQueue.add(
"deployments",
{ ...jobData },
{
removeOnComplete: true,
removeOnFail: true,
},
);
await audit(ctx, {
action: "redeploy",
resourceType: "previewDeployment",
resourceId: input.previewDeploymentId,
});
return true;
}),
});