fix: DDNS update token in body, webdav gating, regression tests
Unit Tests / test (push) Successful in 7m25s

- PicNgoDDNS.update(): send token in request body instead of Authorization
  header; DDNS server validates it from body (was returning HTTP 422 on
  every heartbeat, leaving IP record stale after fresh install)
- peers.py / Peers.jsx: webdav service_access only valid when 'files' store
  service is installed; was always shown even with no services, confusing
  users into thinking WebDAV was pre-installed
- 10 new regression tests: DDNS update body contract, Caddy always
  regenerates on startup with no services, peer role allowed on
  /api/services/active, webdav gating by installed services

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-07 16:56:12 -04:00
parent 962d137093
commit 69862331e7
7 changed files with 241 additions and 12 deletions
+22
View File
@@ -801,6 +801,28 @@ class TestReapplyOnStartup(unittest.TestCase):
with patch('firewall_manager.apply_service_rules'):
ssm.reapply_on_startup() # must not raise
def test_reapply_always_regenerates_caddy_even_with_no_services(self):
"""Caddy must be regenerated on startup even when no store services are installed.
Regression guard: a cell rename or fresh install produces a stale Caddyfile
(wrong domain) if reapply_on_startup() returns early before calling caddy.
"""
ssm = _make_manager(installed={}) # no installed services
ssm.caddy_manager = MagicMock()
ssm.reapply_on_startup()
ssm.caddy_manager.regenerate_with_installed.assert_called_once_with([])
def test_reapply_regenerates_caddy_with_installed_routes(self):
"""When services are installed their caddy_route dicts are passed to regenerate."""
route = {'subdomain': 'myapp', 'backend': 'http://myapp:8080'}
ssm = _make_manager(installed={'myapp': {'service_ip': '172.20.1.10',
'iptables_rules': [],
'caddy_route': route}})
ssm.caddy_manager = MagicMock()
with patch('firewall_manager.apply_service_rules'):
ssm.reapply_on_startup()
ssm.caddy_manager.regenerate_with_installed.assert_called_once_with([route])
if __name__ == '__main__':
unittest.main()