From 702af64444bab39f0aaf68da6f7ae7272d6e8aac Mon Sep 17 00:00:00 2001 From: Mauricio Siu Date: Wed, 10 Dec 2025 00:25:23 -0600 Subject: [PATCH] feat(registry): enhance registry URL validation and update handling - Made the registry URL field optional and added refined validation to ensure only valid hostnames are accepted, excluding protocols and paths. - Updated the handling of registry URL in the form to default to an empty string if not provided. - Added descriptive guidance in the form to assist users in entering the correct format for the registry URL. --- .../cluster/registry/handle-registry.tsx | 37 +++++++++++++++++-- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/apps/dokploy/components/dashboard/settings/cluster/registry/handle-registry.tsx b/apps/dokploy/components/dashboard/settings/cluster/registry/handle-registry.tsx index 4321088f2..dc4b810dd 100644 --- a/apps/dokploy/components/dashboard/settings/cluster/registry/handle-registry.tsx +++ b/apps/dokploy/components/dashboard/settings/cluster/registry/handle-registry.tsx @@ -45,7 +45,34 @@ const AddRegistrySchema = z.object({ password: z.string().min(1, { message: "Password is required", }), - registryUrl: z.string(), + registryUrl: z + .string() + .optional() + .refine( + (val) => { + // If empty or undefined, skip validation (field is optional) + if (!val || val.trim().length === 0) { + return true; + } + // Validate that it's a valid hostname (no protocol, no path, optional port) + // Valid formats: example.com, registry.example.com, [::1], example.com:5000 + // Invalid: https://example.com, example.com/path + const trimmed = val.trim(); + // Check for protocol or path - these are not allowed + if (/^https?:\/\//i.test(trimmed) || trimmed.includes("/")) { + return false; + } + // Basic hostname validation: allow alphanumeric, dots, hyphens, underscores, and IPv6 in brackets + // Allow optional port at the end + const hostnameRegex = + /^(?:\[[^\]]+\]|[a-zA-Z0-9](?:[a-zA-Z0-9._-]{0,253}[a-zA-Z0-9])?)(?::\d+)?$/; + return hostnameRegex.test(trimmed); + }, + { + message: + "Invalid registry URL. Please enter only the hostname (e.g., example.com or registry.example.com). Do not include protocol (https://) or paths.", + }, + ), imagePrefix: z.string(), serverId: z.string().optional(), }); @@ -125,7 +152,7 @@ export const HandleRegistry = ({ registryId }: Props) => { password: data.password, registryName: data.registryName, username: data.username, - registryUrl: data.registryUrl, + registryUrl: data.registryUrl || "", registryType: "cloud", imagePrefix: data.imagePrefix, serverId: data.serverId, @@ -261,6 +288,10 @@ export const HandleRegistry = ({ registryId }: Props) => { render={({ field }) => ( Registry URL + + Enter only the hostname (e.g., + aws_account_id.dkr.ecr.us-west-2.amazonaws.com). + { await testRegistry({ username: username, password: password, - registryUrl: registryUrl, + registryUrl: registryUrl || "", registryName: registryName, registryType: "cloud", imagePrefix: imagePrefix,