From 348fd8faad92d6c58dfc52652805b04ad00bfe03 Mon Sep 17 00:00:00 2001 From: Dmitrii Iurco Date: Tue, 9 Jun 2026 15:09:53 -0400 Subject: [PATCH] Fix Settings: stop auto-registering DDNS on cell name change MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two bugs in the pic_ngo availability + auto-save flow: 1. Availability check fired on page load even when cell_name matched the currently-registered name — sending unnecessary check requests to the DDNS server and showing 'taken' for the user's own name. Fix: skip the check when identity.cell_name === loadedCellName. 2. Auto-save triggered DDNS re-registration (release old subdomain + register new one) as soon as picAvail became 'available' — without the user pressing Accept. This happened because picAvail was in the auto-save effect's dependency array, so it re-ran whenever the availability check completed. Fix: block auto-save entirely for pic_ngo cell name changes; the user must press Accept explicitly since re-registration is irreversible. Co-Authored-By: Claude Sonnet 4.6 --- webui/src/pages/Settings.jsx | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/webui/src/pages/Settings.jsx b/webui/src/pages/Settings.jsx index 1849c91..35c01d5 100644 --- a/webui/src/pages/Settings.jsx +++ b/webui/src/pages/Settings.jsx @@ -458,7 +458,8 @@ function Settings() { useEffect(() => { if (domainMode !== 'pic_ngo') { setPicAvail(null); return; } const name = identity.cell_name; - if (!name) { setPicAvail(null); return; } + // No check needed when the name hasn't changed from what's already registered. + if (!name || name === loadedCellName) { setPicAvail(null); return; } clearTimeout(picAvailTimerRef.current); setPicAvail(null); picAvailTimerRef.current = setTimeout(async () => { @@ -471,7 +472,7 @@ function Settings() { } }, 900); return () => clearTimeout(picAvailTimerRef.current); - }, [identity.cell_name, domainMode]); // eslint-disable-line react-hooks/exhaustive-deps + }, [identity.cell_name, domainMode, loadedCellName]); // eslint-disable-line react-hooks/exhaustive-deps const saveIdentity = useCallback(async () => { if (ipRangeError || cellNameError || domainError) return; @@ -649,15 +650,12 @@ function Settings() { useEffect(() => { if (!identityDirty) return; if (ipRangeError || cellNameError || domainError) return; - // In pic_ngo mode, if the cell name differs from what was last saved/loaded, - // only auto-save once the check confirms the name is available. - // All other states (null, 'checking', 'taken', 'unreachable') block auto-save. - if (domainMode === 'pic_ngo' && identity.cell_name !== loadedCellName) { - if (picAvail !== 'available') return; - } + // pic_ngo cell name changes require DDNS re-registration (irreversible: releases the + // old subdomain). Never auto-save these — the user must explicitly press Accept. + if (domainMode === 'pic_ngo' && identity.cell_name !== loadedCellName) return; const timer = setTimeout(() => saveIdentityRef.current(), 800); return () => clearTimeout(timer); - }, [identity, identityDirty, ipRangeError, cellNameError, domainError, domainMode, picAvail, loadedCellName]); // eslint-disable-line react-hooks/exhaustive-deps + }, [identity, identityDirty, ipRangeError, cellNameError, domainError, domainMode, loadedCellName]); // eslint-disable-line react-hooks/exhaustive-deps useEffect(() => { const timers = SERVICE_DEFS