Skip to content

Commit 85632fd

Browse files
authored
Merge pull request #3219 from Dokploy/feat/add-registry-url-only-allow-hostname
Feat/add registry url only allow hostname
2 parents eef27b6 + 31cdae1 commit 85632fd

File tree

1 file changed

+71
-5
lines changed

1 file changed

+71
-5
lines changed

apps/dokploy/components/dashboard/settings/cluster/registry/handle-registry.tsx

Lines changed: 71 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,34 @@ const AddRegistrySchema = z.object({
4545
password: z.string().min(1, {
4646
message: "Password is required",
4747
}),
48-
registryUrl: z.string(),
48+
registryUrl: z
49+
.string()
50+
.optional()
51+
.refine(
52+
(val) => {
53+
// If empty or undefined, skip validation (field is optional)
54+
if (!val || val.trim().length === 0) {
55+
return true;
56+
}
57+
// Validate that it's a valid hostname (no protocol, no path, optional port)
58+
// Valid formats: example.com, registry.example.com, [::1], example.com:5000
59+
// Invalid: https://example.com, example.com/path
60+
const trimmed = val.trim();
61+
// Check for protocol or path - these are not allowed
62+
if (/^https?:\/\//i.test(trimmed) || trimmed.includes("/")) {
63+
return false;
64+
}
65+
// Basic hostname validation: allow alphanumeric, dots, hyphens, underscores, and IPv6 in brackets
66+
// Allow optional port at the end
67+
const hostnameRegex =
68+
/^(?:\[[^\]]+\]|[a-zA-Z0-9](?:[a-zA-Z0-9._-]{0,253}[a-zA-Z0-9])?)(?::\d+)?$/;
69+
return hostnameRegex.test(trimmed);
70+
},
71+
{
72+
message:
73+
"Invalid registry URL. Please enter only the hostname (e.g., example.com or registry.example.com). Do not include protocol (https://) or paths.",
74+
},
75+
),
4976
imagePrefix: z.string(),
5077
serverId: z.string().optional(),
5178
});
@@ -99,6 +126,9 @@ export const HandleRegistry = ({ registryId }: Props) => {
99126
const registryName = form.watch("registryName");
100127
const imagePrefix = form.watch("imagePrefix");
101128
const serverId = form.watch("serverId");
129+
const selectedServer = servers?.find(
130+
(server) => server.serverId === serverId,
131+
);
102132

103133
useEffect(() => {
104134
if (registry) {
@@ -125,7 +155,7 @@ export const HandleRegistry = ({ registryId }: Props) => {
125155
password: data.password,
126156
registryName: data.registryName,
127157
username: data.username,
128-
registryUrl: data.registryUrl,
158+
registryUrl: data.registryUrl || "",
129159
registryType: "cloud",
130160
imagePrefix: data.imagePrefix,
131161
serverId: data.serverId,
@@ -261,6 +291,10 @@ export const HandleRegistry = ({ registryId }: Props) => {
261291
render={({ field }) => (
262292
<FormItem>
263293
<FormLabel>Registry URL</FormLabel>
294+
<FormDescription>
295+
Enter only the hostname (e.g.,
296+
aws_account_id.dkr.ecr.us-west-2.amazonaws.com).
297+
</FormDescription>
264298
<FormControl>
265299
<Input
266300
placeholder="aws_account_id.dkr.ecr.us-west-2.amazonaws.com"
@@ -282,8 +316,40 @@ export const HandleRegistry = ({ registryId }: Props) => {
282316
<FormItem>
283317
<FormLabel>Server {!isCloud && "(Optional)"}</FormLabel>
284318
<FormDescription>
285-
Select a server to test the registry. this will run the
286-
following command on the server
319+
{!isCloud ? (
320+
<>
321+
{serverId && serverId !== "none" && selectedServer ? (
322+
<>
323+
Authentication will be performed on{" "}
324+
<strong>{selectedServer.name}</strong>. This
325+
registry will be available on this server.
326+
</>
327+
) : (
328+
<>
329+
Choose where to authenticate with the registry. By
330+
default, authentication occurs on the Dokploy
331+
server. Select a specific server to authenticate
332+
from that server instead.
333+
</>
334+
)}
335+
</>
336+
) : (
337+
<>
338+
{serverId && serverId !== "none" && selectedServer ? (
339+
<>
340+
Authentication will be performed on{" "}
341+
<strong>{selectedServer.name}</strong>. This
342+
registry will be available on this server.
343+
</>
344+
) : (
345+
<>
346+
Select a server to authenticate with the registry.
347+
The authentication will be performed from the
348+
selected server.
349+
</>
350+
)}
351+
</>
352+
)}
287353
</FormDescription>
288354
<FormControl>
289355
<Select
@@ -345,7 +411,7 @@ export const HandleRegistry = ({ registryId }: Props) => {
345411
await testRegistry({
346412
username: username,
347413
password: password,
348-
registryUrl: registryUrl,
414+
registryUrl: registryUrl || "",
349415
registryName: registryName,
350416
registryType: "cloud",
351417
imagePrefix: imagePrefix,

0 commit comments

Comments
 (0)