@@ -42,9 +42,7 @@ const AddRegistrySchema = z.object({
4242 username : z . string ( ) . min ( 1 , {
4343 message : "Username is required" ,
4444 } ) ,
45- password : z . string ( ) . min ( 1 , {
46- message : "Password is required" ,
47- } ) ,
45+ password : z . string ( ) ,
4846 registryUrl : z
4947 . string ( )
5048 . optional ( )
@@ -75,6 +73,7 @@ const AddRegistrySchema = z.object({
7573 ) ,
7674 imagePrefix : z . string ( ) ,
7775 serverId : z . string ( ) . optional ( ) ,
76+ isEditing : z . boolean ( ) . optional ( ) ,
7877} ) ;
7978
8079type AddRegistry = z . infer < typeof AddRegistrySchema > ;
@@ -108,6 +107,12 @@ export const HandleRegistry = ({ registryId }: Props) => {
108107 error : testRegistryError ,
109108 isError : testRegistryIsError ,
110109 } = api . registry . testRegistry . useMutation ( ) ;
110+ const {
111+ mutateAsync : testRegistryById ,
112+ isLoading : isLoadingById ,
113+ error : testRegistryByIdError ,
114+ isError : testRegistryByIdIsError ,
115+ } = api . registry . testRegistryById . useMutation ( ) ;
111116 const form = useForm < AddRegistry > ( {
112117 defaultValues : {
113118 username : "" ,
@@ -116,8 +121,26 @@ export const HandleRegistry = ({ registryId }: Props) => {
116121 imagePrefix : "" ,
117122 registryName : "" ,
118123 serverId : "" ,
124+ isEditing : ! ! registryId ,
119125 } ,
120- resolver : zodResolver ( AddRegistrySchema ) ,
126+ resolver : zodResolver (
127+ AddRegistrySchema . refine (
128+ ( data ) => {
129+ // When creating a new registry, password is required
130+ if (
131+ ! data . isEditing &&
132+ ( ! data . password || data . password . length === 0 )
133+ ) {
134+ return false ;
135+ }
136+ return true ;
137+ } ,
138+ {
139+ message : "Password is required" ,
140+ path : [ "password" ] ,
141+ } ,
142+ ) ,
143+ ) ,
121144 } ) ;
122145
123146 const password = form . watch ( "password" ) ;
@@ -138,6 +161,7 @@ export const HandleRegistry = ({ registryId }: Props) => {
138161 registryUrl : registry . registryUrl ,
139162 imagePrefix : registry . imagePrefix || "" ,
140163 registryName : registry . registryName ,
164+ isEditing : true ,
141165 } ) ;
142166 } else {
143167 form . reset ( {
@@ -146,21 +170,29 @@ export const HandleRegistry = ({ registryId }: Props) => {
146170 registryUrl : "" ,
147171 imagePrefix : "" ,
148172 serverId : "" ,
173+ isEditing : false ,
149174 } ) ;
150175 }
151176 } , [ form , form . reset , form . formState . isSubmitSuccessful , registry ] ) ;
152177
153178 const onSubmit = async ( data : AddRegistry ) => {
154- await mutateAsync ( {
155- password : data . password ,
179+ const payload : any = {
156180 registryName : data . registryName ,
157181 username : data . username ,
158182 registryUrl : data . registryUrl || "" ,
159183 registryType : "cloud" ,
160184 imagePrefix : data . imagePrefix ,
161185 serverId : data . serverId ,
162186 registryId : registryId || "" ,
163- } )
187+ } ;
188+
189+ // Only include password if it's been provided (not empty)
190+ // When editing, empty password means "keep the existing password"
191+ if ( data . password && data . password . length > 0 ) {
192+ payload . password = data . password ;
193+ }
194+
195+ await mutateAsync ( payload )
164196 . then ( async ( _data ) => {
165197 await utils . registry . all . invalidate ( ) ;
166198 toast . success ( registryId ? "Registry updated" : "Registry added" ) ;
@@ -198,11 +230,14 @@ export const HandleRegistry = ({ registryId }: Props) => {
198230 Fill the next fields to add a external registry.
199231 </ DialogDescription >
200232 </ DialogHeader >
201- { ( isError || testRegistryIsError ) && (
233+ { ( isError || testRegistryIsError || testRegistryByIdIsError ) && (
202234 < div className = "flex flex-row gap-4 rounded-lg bg-red-50 p-2 dark:bg-red-950" >
203235 < AlertTriangle className = "text-red-600 dark:text-red-400" />
204236 < span className = "text-sm text-red-600 dark:text-red-400" >
205- { testRegistryError ?. message || error ?. message || "" }
237+ { testRegistryError ?. message ||
238+ testRegistryByIdError ?. message ||
239+ error ?. message ||
240+ "" }
206241 </ span >
207242 </ div >
208243 ) }
@@ -253,10 +288,20 @@ export const HandleRegistry = ({ registryId }: Props) => {
253288 name = "password"
254289 render = { ( { field } ) => (
255290 < FormItem >
256- < FormLabel > Password</ FormLabel >
291+ < FormLabel > Password{ registryId && " (Optional)" } </ FormLabel >
292+ { registryId && (
293+ < FormDescription >
294+ Leave blank to keep existing password. Enter new
295+ password to test or update it.
296+ </ FormDescription >
297+ ) }
257298 < FormControl >
258299 < Input
259- placeholder = "Password"
300+ placeholder = {
301+ registryId
302+ ? "Leave blank to keep existing"
303+ : "Password"
304+ }
260305 autoComplete = "one-time-code"
261306 { ...field }
262307 type = "password"
@@ -387,15 +432,45 @@ export const HandleRegistry = ({ registryId }: Props) => {
387432 < Button
388433 type = "button"
389434 variant = { "secondary" }
390- isLoading = { isLoading }
435+ isLoading = { isLoading || isLoadingById }
391436 onClick = { async ( ) => {
437+ // When editing with empty password, use the existing password from DB
438+ if ( registryId && ( ! password || password . length === 0 ) ) {
439+ await testRegistryById ( {
440+ registryId : registryId || "" ,
441+ ...( serverId && { serverId } ) ,
442+ } )
443+ . then ( ( data ) => {
444+ if ( data ) {
445+ toast . success ( "Registry Tested Successfully" ) ;
446+ } else {
447+ toast . error ( "Registry Test Failed" ) ;
448+ }
449+ } )
450+ . catch ( ( ) => {
451+ toast . error ( "Error testing the registry" ) ;
452+ } ) ;
453+ return ;
454+ }
455+
456+ // When creating, password is required
457+ if ( ! registryId && ( ! password || password . length === 0 ) ) {
458+ form . setError ( "password" , {
459+ type : "manual" ,
460+ message : "Password is required" ,
461+ } ) ;
462+ return ;
463+ }
464+
465+ // When creating or editing with new password, validate and test with provided credentials
392466 const validationResult = AddRegistrySchema . safeParse ( {
393467 username,
394468 password,
395469 registryUrl,
396470 registryName : "Dokploy Registry" ,
397471 imagePrefix,
398472 serverId,
473+ isEditing : ! ! registryId ,
399474 } ) ;
400475
401476 if ( ! validationResult . success ) {
0 commit comments