Setup wizard (Issue 1 — UI): - pic.ngo subdomain input now uses the same split-field style as DuckDNS: input + static '.pic.ngo' suffix in a flex row, availability status below Setup wizard (Issue 2 — Caddy not regenerating after completion): - complete_setup route now fires IDENTITY_CHANGED after a successful wizard submission so CaddyManager regenerates the Caddyfile immediately; users no longer need to press 'Renew Certificate' to start ACME Settings — DDNS status (Issue 2 — domain status missing): - New GET /api/ddns/status endpoint: returns registered flag, domain_name, public_ip (ipify with 30s cache), last_ip from heartbeat - Settings DDNS section for pic_ngo now shows a live status row with color-coded dot (green=registered+current, yellow=registered+stale, gray=not registered), current public IP, and a Check button - Status auto-refreshes on mount and after each successful re-registration Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -586,6 +586,42 @@ def update_ddns_config():
|
||||
return jsonify({'error': str(e)}), 500
|
||||
|
||||
|
||||
_ddns_public_ip_cache: dict = {'ip': None, 'at': 0}
|
||||
|
||||
@bp.route('/api/ddns/status', methods=['GET'])
|
||||
def ddns_status():
|
||||
import time as _time
|
||||
from app import config_manager
|
||||
ddns_cfg = config_manager.configs.get('ddns', {})
|
||||
identity = config_manager.configs.get('_identity', {})
|
||||
|
||||
now = _time.time()
|
||||
if now - _ddns_public_ip_cache['at'] > 30 or not _ddns_public_ip_cache['ip']:
|
||||
try:
|
||||
import requests as _req
|
||||
resp = _req.get('https://api.ipify.org', timeout=5)
|
||||
if resp.ok:
|
||||
_ddns_public_ip_cache['ip'] = resp.text.strip()
|
||||
_ddns_public_ip_cache['at'] = now
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
last_ip = None
|
||||
try:
|
||||
from app import ddns_manager as _ddns_mgr_singleton
|
||||
last_ip = _ddns_mgr_singleton._last_ip
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
registered = bool(ddns_cfg.get('token'))
|
||||
return jsonify({
|
||||
'registered': registered,
|
||||
'domain_name': identity.get('domain_name', ''),
|
||||
'public_ip': _ddns_public_ip_cache['ip'],
|
||||
'last_ip': last_ip,
|
||||
})
|
||||
|
||||
|
||||
@bp.route('/api/ddns/register', methods=['POST'])
|
||||
def ddns_register():
|
||||
"""Trigger (re-)registration with the configured DDNS provider."""
|
||||
|
||||
Reference in New Issue
Block a user