Refactor UI assets and harden quality checks

This commit is contained in:
StasonJatham committed 2026-06-17 23:18:00 +02:00
1 parent 23ab466c52
commit 4ecc8eb874
62 files changed
+3314 -3206

No files matched your search

+89 -42
View File
@@ -1,67 +1,114 @@
from __future__ import annotations
from dataclasses import dataclass
from typing import Any, Protocol
from ..models import UpdateResult
from ..settings import DdnsSettings
from .base import DnsProviderError
class _RcodeResponse(Protocol):
def rcode(self) -> int: ...
@dataclass(frozen=True, slots=True)
class _RecordUpdate:
ttl: int
record_type: str
value: str | None
enabled: bool
def publish_rfc2136(result: UpdateResult, settings: DdnsSettings) -> None:
if not settings.rfc2136_server:
return
import dns.exception
import dns.query
import dns.rcode
import dns.tsigkeyring
import dns.update
keyring = None
if settings.rfc2136_key_name and settings.rfc2136_key_secret:
keyring = dns.tsigkeyring.from_text({settings.rfc2136_key_name: settings.rfc2136_key_secret})
zone = settings.rfc2136_zone or ".".join(result.hostname.split(".")[1:])
update = dns.update.Update(zone, keyring=keyring)
relative = result.hostname.removesuffix("." + zone).rstrip(".") or "@"
if result.update_ipv4 and result.ipv4:
update.replace(relative, settings.ttl, "A", result.ipv4)
elif result.update_ipv4:
update.delete(relative, "A")
if result.update_ipv6 and result.ipv6:
update.replace(relative, settings.ttl, "AAAA", result.ipv6)
elif result.update_ipv6:
update.delete(relative, "AAAA")
try:
response = dns.query.tcp(update, settings.rfc2136_server, timeout=5)
except dns.exception.DNSException as exc:
raise DnsProviderError("RFC2136 DNS update failed") from exc
rcode = response.rcode()
if rcode != 0:
raise DnsProviderError(f"RFC2136 update failed: {dns.rcode.to_text(rcode)}")
update, relative = _rfc2136_update(result.hostname, settings)
_apply_update_records(update, relative, result, settings)
_send_rfc2136_update(update, settings.rfc2136_server, "update")
def delete_rfc2136_records(hostname: str, settings: DdnsSettings) -> None:
if not settings.rfc2136_server:
return
update, relative = _rfc2136_update(hostname, settings)
update.delete(relative, "A")
update.delete(relative, "AAAA")
_send_rfc2136_update(update, settings.rfc2136_server, "delete")
def _rfc2136_update(hostname: str, settings: DdnsSettings) -> tuple[Any, str]:
import dns.update
zone = _rfc2136_zone(hostname, settings)
update = dns.update.Update(zone, keyring=_rfc2136_keyring(settings))
return update, _rfc2136_relative_name(hostname, zone)
def _rfc2136_zone(hostname: str, settings: DdnsSettings) -> str:
return settings.rfc2136_zone or ".".join(hostname.split(".")[1:])
def _rfc2136_relative_name(hostname: str, zone: str) -> str:
hostname = hostname.rstrip(".")
zone = zone.rstrip(".")
if hostname == zone:
return "@"
return hostname.removesuffix("." + zone).rstrip(".") or "@"
def _rfc2136_keyring(settings: DdnsSettings) -> Any | None:
if not settings.rfc2136_key_name or not settings.rfc2136_key_secret:
return None
import dns.tsigkeyring
return dns.tsigkeyring.from_text({settings.rfc2136_key_name: settings.rfc2136_key_secret})
def _apply_update_records(update: Any, relative: str, result: UpdateResult, settings: DdnsSettings) -> None:
_apply_record_update(
update,
relative,
_RecordUpdate(ttl=settings.ttl, record_type="A", value=result.ipv4, enabled=result.update_ipv4),
)
_apply_record_update(
update,
relative,
_RecordUpdate(ttl=settings.ttl, record_type="AAAA", value=result.ipv6, enabled=result.update_ipv6),
)
def _apply_record_update(
update: Any,
relative: str,
record: _RecordUpdate,
) -> None:
if not record.enabled:
return
if record.value is None:
update.delete(relative, record.record_type)
return
update.replace(relative, record.ttl, record.record_type, record.value)
def _send_rfc2136_update(update: Any, server: str, operation: str) -> None:
import dns.exception
import dns.query
import dns.rcode
import dns.tsigkeyring
import dns.update
keyring = None
if settings.rfc2136_key_name and settings.rfc2136_key_secret:
keyring = dns.tsigkeyring.from_text({settings.rfc2136_key_name: settings.rfc2136_key_secret})
zone = settings.rfc2136_zone or ".".join(hostname.split(".")[1:])
update = dns.update.Update(zone, keyring=keyring)
relative = hostname.removesuffix("." + zone).rstrip(".") or "@"
update.delete(relative, "A")
update.delete(relative, "AAAA")
try:
response = dns.query.tcp(update, settings.rfc2136_server, timeout=5)
response = dns.query.tcp(update, server, timeout=5)
except dns.exception.DNSException as exc:
raise DnsProviderError("RFC2136 DNS delete failed") from exc
raise DnsProviderError(f"RFC2136 DNS {operation} failed") from exc
_raise_for_rfc2136_response(response, operation)
def _raise_for_rfc2136_response(response: _RcodeResponse, operation: str) -> None:
import dns.rcode
rcode = response.rcode()
if rcode != 0:
raise DnsProviderError(f"RFC2136 delete failed: {dns.rcode.to_text(rcode)}")
raise DnsProviderError(f"RFC2136 {operation} failed: {dns.rcode.to_text(dns.rcode.Rcode(rcode))}")