fix: use effective_domain for service links and clean up stale DNS records
Unit Tests / test (push) Successful in 11m32s

Dashboard, Email, Calendar, and Files pages were building service URLs
with the internal LAN zone name (e.g. 'cell') instead of the public
effective domain (e.g. 'pic2.pic.ngo'), and always using http:// even
in DDNS mode where HTTPS is available.

Changes:
- Dashboard/Email/Calendar/Files: read effective_domain + domain_mode
  from ConfigContext; use effective_domain in non-LAN mode and https://
  for all DDNS domain modes.
- Calendar: show port 443 instead of 80 in DDNS mode.
- network_manager.update_split_horizon_zone: when the primary internal
  zone name is a parent of the effective DDNS domain (e.g. pic.ngo is a
  parent of pic2.pic.ngo), remove stale bootstrap service records (api,
  calendar, files, mail, webmail, webdav) that pollute the DNS display
  and would shadow public DNS responses.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-28 05:06:52 -04:00
parent d7dbd596ab
commit 66500bb128
6 changed files with 83 additions and 26 deletions
+37
View File
@@ -458,6 +458,43 @@ class TestUpdateSplitHorizonZone(unittest.TestCase):
calls = [str(c) for c in mock_run.call_args_list]
self.assertTrue(any('SIGUSR1' in c for c in calls))
@patch('subprocess.run')
def test_removes_stale_service_records_when_primary_is_parent(self, _mock):
"""Stale LAN service names (api, calendar…) are removed from a parent zone."""
# Bootstrap a pic.ngo zone with service records (wrong internal zone name)
stale_records = [
{'name': 'pic2', 'type': 'A', 'value': '10.0.0.1'},
{'name': 'api', 'type': 'A', 'value': '10.0.0.1'},
{'name': 'calendar','type': 'A', 'value': '10.0.0.1'},
{'name': 'files', 'type': 'A', 'value': '10.0.0.1'},
]
self.nm.update_dns_zone('pic.ngo', stale_records)
# update_split_horizon_zone should strip api/calendar/files from pic.ngo
self.nm.update_split_horizon_zone(
'pic2.pic.ngo', '172.20.0.2', primary_domain='pic.ngo'
)
content = open(os.path.join(self.data_dir, 'dns', 'pic.ngo.zone')).read()
self.assertNotIn('calendar', content)
self.assertNotIn('\napi ', content)
self.assertNotIn('\nfiles ', content)
# Non-stale record (pic2 is the cell_name, not in _stale set) survives
# but api/calendar/files are gone
self.assertIn('172.20.0.2', open(
os.path.join(self.data_dir, 'dns', 'pic2.pic.ngo.zone')).read())
@patch('subprocess.run')
def test_no_stale_cleanup_when_primary_not_parent(self, _mock):
"""When primary_domain is unrelated, no zone file is touched."""
stale_records = [{'name': 'calendar', 'type': 'A', 'value': '10.0.0.1'}]
self.nm.update_dns_zone('cell', stale_records)
self.nm.update_split_horizon_zone(
'pic2.pic.ngo', '172.20.0.2', primary_domain='cell'
)
# cell zone is untouched
content = open(os.path.join(self.data_dir, 'dns', 'cell.zone')).read()
self.assertIn('calendar', content)
if __name__ == '__main__':
unittest.main()