From 399bcb03022201cda6138332d3d9ca37027b549d Mon Sep 17 00:00:00 2001
From: Mauricio Siu <47042324+Siumauricio@users.noreply.github.com>
Date: Mon, 1 Sep 2025 20:36:03 -0600
Subject: [PATCH] refactor: update project and API components to utilize
environment context for organization authorization checks and enhance service
retrieval methods
---
.../components/dashboard/projects/show.tsx | 117 ++++++++++--------
apps/dokploy/server/api/routers/domain.ts | 22 ++--
.../server/api/routers/preview-deployment.ts | 6 +-
.../server/src/services/preview-deployment.ts | 37 +-----
4 files changed, 82 insertions(+), 100 deletions(-)
diff --git a/apps/dokploy/components/dashboard/projects/show.tsx b/apps/dokploy/components/dashboard/projects/show.tsx
index 4cdac8e52..bba892857 100644
--- a/apps/dokploy/components/dashboard/projects/show.tsx
+++ b/apps/dokploy/components/dashboard/projects/show.tsx
@@ -187,23 +187,28 @@ export const ShowProjects = () => {
)}
{filteredProjects?.map((project) => {
- // const emptyServices =
- // project?.environments.length === 0 &&
- // project?.mongo.length === 0 &&
- // project?.environments.mysql.length === 0 &&
- // project?.environments.postgres.length === 0 &&
- // project?.environments.redis.length === 0 &&
- // project?.applications.length === 0 &&
- // project?.compose.length === 0;
+ const emptyServices =
+ project?.environments.map((env) => env.applications.length === 0 &&
+ env.mariadb.length === 0 &&
+ env.mongo.length === 0 &&
+ env.mysql.length === 0 &&
+ env.postgres.length === 0 &&
+ env.redis.length === 0 &&
+ env.applications.length === 0 &&
+ env.compose.length === 0).every(Boolean);
- // const totalServices =
- // project?.mariadb.length +
- // project?.mongo.length +
- // project?.mysql.length +
- // project?.postgres.length +
- // project?.redis.length +
- // project?.applications.length +
- // project?.compose.length;
+ const totalServices =
+ project?.environments.map((env) => env.mariadb.length +
+ env.mongo.length +
+ env.mysql.length +
+ env.postgres.length +
+ env.redis.length +
+ env.applications.length +
+ env.compose.length ).reduce((acc, curr) => acc + curr, 0);
+
+ const haveServicesWithDomains =
+ project?.environments.map((env) => env.applications.length > 0 ||
+ env.compose.length > 0).some(Boolean);
return (
{
href={`/dashboard/project/${project.projectId}`}
>
- {/* {project.applications.length > 0 ||
- project.compose.length > 0 ? (
+ {haveServicesWithDomains ? (
))}
- )}
+ )} */}
- ) : null} */}
+ ) : null}
@@ -379,7 +386,7 @@ export const ShowProjects = () => {
Are you sure to delete this
project?
- {/* {!emptyServices ? (
+ {!emptyServices ? (
@@ -393,14 +400,14 @@ export const ShowProjects = () => {
This action cannot be
undone
- )} */}
+ )}
Cancel
{
await mutateAsync({
projectId:
@@ -438,12 +445,12 @@ export const ShowProjects = () => {
Created
- {/*
+
{totalServices}{" "}
{totalServices === 1
? "service"
: "services"}
- */}
+
diff --git a/apps/dokploy/server/api/routers/domain.ts b/apps/dokploy/server/api/routers/domain.ts
index 7c16baf34..d2d40419c 100644
--- a/apps/dokploy/server/api/routers/domain.ts
+++ b/apps/dokploy/server/api/routers/domain.ts
@@ -34,7 +34,7 @@ export const domainRouter = createTRPCRouter({
if (input.domainType === "compose" && input.composeId) {
const compose = await findComposeById(input.composeId);
if (
- compose.project.organizationId !== ctx.session.activeOrganizationId
+ compose.environment.project.organizationId !== ctx.session.activeOrganizationId
) {
throw new TRPCError({
code: "UNAUTHORIZED",
@@ -44,7 +44,7 @@ export const domainRouter = createTRPCRouter({
} else if (input.domainType === "application" && input.applicationId) {
const application = await findApplicationById(input.applicationId);
if (
- application.project.organizationId !==
+ application.environment.project.organizationId !==
ctx.session.activeOrganizationId
) {
throw new TRPCError({
@@ -70,7 +70,7 @@ export const domainRouter = createTRPCRouter({
.query(async ({ input, ctx }) => {
const application = await findApplicationById(input.applicationId);
if (
- application.project.organizationId !== ctx.session.activeOrganizationId
+ application.environment.project.organizationId !== ctx.session.activeOrganizationId
) {
throw new TRPCError({
code: "UNAUTHORIZED",
@@ -83,7 +83,7 @@ export const domainRouter = createTRPCRouter({
.input(apiFindCompose)
.query(async ({ input, ctx }) => {
const compose = await findComposeById(input.composeId);
- if (compose.project.organizationId !== ctx.session.activeOrganizationId) {
+ if (compose.environment.project.organizationId !== ctx.session.activeOrganizationId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to access this compose",
@@ -122,7 +122,7 @@ export const domainRouter = createTRPCRouter({
if (currentDomain.applicationId) {
const newApp = await findApplicationById(currentDomain.applicationId);
if (
- newApp.project.organizationId !== ctx.session.activeOrganizationId
+ newApp.environment.project.organizationId !== ctx.session.activeOrganizationId
) {
throw new TRPCError({
code: "UNAUTHORIZED",
@@ -132,7 +132,7 @@ export const domainRouter = createTRPCRouter({
} else if (currentDomain.composeId) {
const newCompose = await findComposeById(currentDomain.composeId);
if (
- newCompose.project.organizationId !== ctx.session.activeOrganizationId
+ newCompose.environment.project.organizationId !== ctx.session.activeOrganizationId
) {
throw new TRPCError({
code: "UNAUTHORIZED",
@@ -144,7 +144,7 @@ export const domainRouter = createTRPCRouter({
currentDomain.previewDeploymentId,
);
if (
- newPreviewDeployment.application.project.organizationId !==
+ newPreviewDeployment.application.environment.project.organizationId !==
ctx.session.activeOrganizationId
) {
throw new TRPCError({
@@ -175,7 +175,7 @@ export const domainRouter = createTRPCRouter({
if (domain.applicationId) {
const application = await findApplicationById(domain.applicationId);
if (
- application.project.organizationId !== ctx.session.activeOrganizationId
+ application.environment.project.organizationId !== ctx.session.activeOrganizationId
) {
throw new TRPCError({
code: "UNAUTHORIZED",
@@ -184,7 +184,7 @@ export const domainRouter = createTRPCRouter({
}
} else if (domain.composeId) {
const compose = await findComposeById(domain.composeId);
- if (compose.project.organizationId !== ctx.session.activeOrganizationId) {
+ if (compose.environment.project.organizationId !== ctx.session.activeOrganizationId) {
throw new TRPCError({
code: "UNAUTHORIZED",
message: "You are not authorized to access this compose",
@@ -200,7 +200,7 @@ export const domainRouter = createTRPCRouter({
if (domain.applicationId) {
const application = await findApplicationById(domain.applicationId);
if (
- application.project.organizationId !==
+ application.environment.project.organizationId !==
ctx.session.activeOrganizationId
) {
throw new TRPCError({
@@ -211,7 +211,7 @@ export const domainRouter = createTRPCRouter({
} else if (domain.composeId) {
const compose = await findComposeById(domain.composeId);
if (
- compose.project.organizationId !== ctx.session.activeOrganizationId
+ compose.environment.project.organizationId !== ctx.session.activeOrganizationId
) {
throw new TRPCError({
code: "UNAUTHORIZED",
diff --git a/apps/dokploy/server/api/routers/preview-deployment.ts b/apps/dokploy/server/api/routers/preview-deployment.ts
index d4cf16f4e..0aae5a65d 100644
--- a/apps/dokploy/server/api/routers/preview-deployment.ts
+++ b/apps/dokploy/server/api/routers/preview-deployment.ts
@@ -15,7 +15,7 @@ export const previewDeploymentRouter = createTRPCRouter({
.query(async ({ input, ctx }) => {
const application = await findApplicationById(input.applicationId);
if (
- application.project.organizationId !== ctx.session.activeOrganizationId
+ application.environment.project.organizationId !== ctx.session.activeOrganizationId
) {
throw new TRPCError({
code: "UNAUTHORIZED",
@@ -31,7 +31,7 @@ export const previewDeploymentRouter = createTRPCRouter({
input.previewDeploymentId,
);
if (
- previewDeployment.application.project.organizationId !==
+ previewDeployment.application.environment.project.organizationId !==
ctx.session.activeOrganizationId
) {
throw new TRPCError({
@@ -49,7 +49,7 @@ export const previewDeploymentRouter = createTRPCRouter({
input.previewDeploymentId,
);
if (
- previewDeployment.application.project.organizationId !==
+ previewDeployment.application.environment.project.organizationId !==
ctx.session.activeOrganizationId
) {
throw new TRPCError({
diff --git a/packages/server/src/services/preview-deployment.ts b/packages/server/src/services/preview-deployment.ts
index 44d1604ae..03346aae6 100644
--- a/packages/server/src/services/preview-deployment.ts
+++ b/packages/server/src/services/preview-deployment.ts
@@ -31,7 +31,11 @@ export const findPreviewDeploymentById = async (
application: {
with: {
server: true,
- project: true,
+ environment: {
+ with: {
+ project: true,
+ },
+ },
},
},
},
@@ -45,36 +49,7 @@ export const findPreviewDeploymentById = async (
return application;
};
-export const findApplicationByPreview = async (applicationId: string) => {
- const application = await db.query.applications.findFirst({
- with: {
- previewDeployments: {
- where: eq(previewDeployments.applicationId, applicationId),
- },
- project: true,
- domains: true,
- deployments: true,
- mounts: true,
- redirects: true,
- security: true,
- ports: true,
- registry: true,
- gitlab: true,
- github: true,
- bitbucket: true,
- gitea: true,
- server: true,
- },
- });
- if (!application) {
- throw new TRPCError({
- code: "NOT_FOUND",
- message: "Application not found",
- });
- }
- return application;
-};
export const removePreviewDeployment = async (previewDeploymentId: string) => {
try {
@@ -163,7 +138,7 @@ export const createPreviewDeployment = async (
const appName = `preview-${application.appName}-${generatePassword(6)}`;
const org = await db.query.organization.findFirst({
- where: eq(organization.id, application.project.organizationId),
+ where: eq(organization.id, application.environment.project.organizationId),
});
const generateDomain = await generateWildcardDomain(
application.previewWildcard || "*.traefik.me",