Skip to content

Commit ca7d3f8

Browse files
authored
Merge pull request #3599 from Dokploy/copilot/fix-postgres-deployment-port-conflict
fix: add port conflict validation for database external ports
2 parents 33802f5 + 66448ff commit ca7d3f8

10 files changed

Lines changed: 94 additions & 19 deletions

File tree

apps/dokploy/components/dashboard/mariadb/general/show-external-mariadb-credentials.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,8 @@ export const ShowExternalMariadbCredentials = ({ mariadbId }: Props) => {
7373
toast.success("External Port updated");
7474
await refetch();
7575
})
76-
.catch(() => {
77-
toast.error("Error saving the external port");
76+
.catch((error: Error) => {
77+
toast.error(error?.message || "Error saving the external port");
7878
});
7979
};
8080

apps/dokploy/components/dashboard/mongo/general/show-external-mongo-credentials.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,8 @@ export const ShowExternalMongoCredentials = ({ mongoId }: Props) => {
7373
toast.success("External Port updated");
7474
await refetch();
7575
})
76-
.catch(() => {
77-
toast.error("Error saving the external port");
76+
.catch((error: Error) => {
77+
toast.error(error?.message || "Error saving the external port");
7878
});
7979
};
8080

apps/dokploy/components/dashboard/mysql/general/show-external-mysql-credentials.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,8 @@ export const ShowExternalMysqlCredentials = ({ mysqlId }: Props) => {
7373
toast.success("External Port updated");
7474
await refetch();
7575
})
76-
.catch(() => {
77-
toast.error("Error saving the external port");
76+
.catch((error: Error) => {
77+
toast.error(error?.message || "Error saving the external port");
7878
});
7979
};
8080

apps/dokploy/components/dashboard/postgres/general/show-external-postgres-credentials.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,8 @@ export const ShowExternalPostgresCredentials = ({ postgresId }: Props) => {
7575
toast.success("External Port updated");
7676
await refetch();
7777
})
78-
.catch(() => {
79-
toast.error("Error saving the external port");
78+
.catch((error: Error) => {
79+
toast.error(error?.message || "Error saving the external port");
8080
});
8181
};
8282

apps/dokploy/components/dashboard/redis/general/show-external-redis-credentials.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,8 @@ export const ShowExternalRedisCredentials = ({ redisId }: Props) => {
7474
toast.success("External Port updated");
7575
await refetch();
7676
})
77-
.catch(() => {
78-
toast.error("Error saving the external port");
77+
.catch((error: Error) => {
78+
toast.error(error?.message || "Error saving the external port");
7979
});
8080
};
8181

apps/dokploy/server/api/routers/mariadb.ts

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import {
22
addNewService,
3+
checkPortInUse,
34
checkServiceAccess,
45
createMariadb,
56
createMount,
@@ -162,21 +163,35 @@ export const mariadbRouter = createTRPCRouter({
162163
saveExternalPort: protectedProcedure
163164
.input(apiSaveExternalPortMariaDB)
164165
.mutation(async ({ input, ctx }) => {
165-
const mongo = await findMariadbById(input.mariadbId);
166+
const mariadb = await findMariadbById(input.mariadbId);
166167
if (
167-
mongo.environment.project.organizationId !==
168+
mariadb.environment.project.organizationId !==
168169
ctx.session.activeOrganizationId
169170
) {
170171
throw new TRPCError({
171172
code: "UNAUTHORIZED",
172173
message: "You are not authorized to save this external port",
173174
});
174175
}
176+
177+
if (input.externalPort) {
178+
const portCheck = await checkPortInUse(
179+
input.externalPort,
180+
mariadb.serverId || undefined,
181+
);
182+
if (portCheck.isInUse) {
183+
throw new TRPCError({
184+
code: "CONFLICT",
185+
message: `Port ${input.externalPort} is already in use by ${portCheck.conflictingContainer}`,
186+
});
187+
}
188+
}
189+
175190
await updateMariadbById(input.mariadbId, {
176191
externalPort: input.externalPort,
177192
});
178193
await deployMariadb(input.mariadbId);
179-
return mongo;
194+
return mariadb;
180195
}),
181196
deploy: protectedProcedure
182197
.input(apiDeployMariaDB)

apps/dokploy/server/api/routers/mongo.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import {
22
addNewService,
3+
checkPortInUse,
34
checkServiceAccess,
45
createMongo,
56
createMount,
@@ -189,6 +190,20 @@ export const mongoRouter = createTRPCRouter({
189190
message: "You are not authorized to save this external port",
190191
});
191192
}
193+
194+
if (input.externalPort) {
195+
const portCheck = await checkPortInUse(
196+
input.externalPort,
197+
mongo.serverId || undefined,
198+
);
199+
if (portCheck.isInUse) {
200+
throw new TRPCError({
201+
code: "CONFLICT",
202+
message: `Port ${input.externalPort} is already in use by ${portCheck.conflictingContainer}`,
203+
});
204+
}
205+
}
206+
192207
await updateMongoById(input.mongoId, {
193208
externalPort: input.externalPort,
194209
});

apps/dokploy/server/api/routers/mysql.ts

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import {
22
addNewService,
3+
checkPortInUse,
34
checkServiceAccess,
45
createMount,
56
createMysql,
@@ -177,21 +178,35 @@ export const mysqlRouter = createTRPCRouter({
177178
saveExternalPort: protectedProcedure
178179
.input(apiSaveExternalPortMySql)
179180
.mutation(async ({ input, ctx }) => {
180-
const mongo = await findMySqlById(input.mysqlId);
181+
const mysql = await findMySqlById(input.mysqlId);
181182
if (
182-
mongo.environment.project.organizationId !==
183+
mysql.environment.project.organizationId !==
183184
ctx.session.activeOrganizationId
184185
) {
185186
throw new TRPCError({
186187
code: "UNAUTHORIZED",
187188
message: "You are not authorized to save this external port",
188189
});
189190
}
191+
192+
if (input.externalPort) {
193+
const portCheck = await checkPortInUse(
194+
input.externalPort,
195+
mysql.serverId || undefined,
196+
);
197+
if (portCheck.isInUse) {
198+
throw new TRPCError({
199+
code: "CONFLICT",
200+
message: `Port ${input.externalPort} is already in use by ${portCheck.conflictingContainer}`,
201+
});
202+
}
203+
}
204+
190205
await updateMySqlById(input.mysqlId, {
191206
externalPort: input.externalPort,
192207
});
193208
await deployMySql(input.mysqlId);
194-
return mongo;
209+
return mysql;
195210
}),
196211
deploy: protectedProcedure
197212
.input(apiDeployMySql)

apps/dokploy/server/api/routers/postgres.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import {
22
addNewService,
3+
checkPortInUse,
34
checkServiceAccess,
45
createMount,
56
createPostgres,
@@ -192,6 +193,20 @@ export const postgresRouter = createTRPCRouter({
192193
message: "You are not authorized to save this external port",
193194
});
194195
}
196+
197+
if (input.externalPort) {
198+
const portCheck = await checkPortInUse(
199+
input.externalPort,
200+
postgres.serverId || undefined,
201+
);
202+
if (portCheck.isInUse) {
203+
throw new TRPCError({
204+
code: "CONFLICT",
205+
message: `Port ${input.externalPort} is already in use by ${portCheck.conflictingContainer}`,
206+
});
207+
}
208+
}
209+
195210
await updatePostgresById(input.postgresId, {
196211
externalPort: input.externalPort,
197212
});

apps/dokploy/server/api/routers/redis.ts

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import {
22
addNewService,
3+
checkPortInUse,
34
checkServiceAccess,
45
createMount,
56
createRedis,
@@ -201,21 +202,35 @@ export const redisRouter = createTRPCRouter({
201202
saveExternalPort: protectedProcedure
202203
.input(apiSaveExternalPortRedis)
203204
.mutation(async ({ input, ctx }) => {
204-
const mongo = await findRedisById(input.redisId);
205+
const redis = await findRedisById(input.redisId);
205206
if (
206-
mongo.environment.project.organizationId !==
207+
redis.environment.project.organizationId !==
207208
ctx.session.activeOrganizationId
208209
) {
209210
throw new TRPCError({
210211
code: "UNAUTHORIZED",
211212
message: "You are not authorized to save this external port",
212213
});
213214
}
215+
216+
if (input.externalPort) {
217+
const portCheck = await checkPortInUse(
218+
input.externalPort,
219+
redis.serverId || undefined,
220+
);
221+
if (portCheck.isInUse) {
222+
throw new TRPCError({
223+
code: "CONFLICT",
224+
message: `Port ${input.externalPort} is already in use by ${portCheck.conflictingContainer}`,
225+
});
226+
}
227+
}
228+
214229
await updateRedisById(input.redisId, {
215230
externalPort: input.externalPort,
216231
});
217232
await deployRedis(input.redisId);
218-
return mongo;
233+
return redis;
219234
}),
220235
deploy: protectedProcedure
221236
.input(apiDeployRedis)

0 commit comments

Comments
 (0)