From: Aleš Mrázek Date: Wed, 13 Apr 2022 14:57:36 +0000 (+0200) Subject: manager: datamodel: types: allow root-zone in DomainName X-Git-Tag: v6.0.0a1~37^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=08fe1e2c0ddf9bca53f4a47d5d19e043f8e435c4;p=thirdparty%2Fknot-resolver.git manager: datamodel: types: allow root-zone in DomainName --- diff --git a/manager/knot_resolver_manager/datamodel/cache_schema.py b/manager/knot_resolver_manager/datamodel/cache_schema.py index 493464807..bb99ce410 100644 --- a/manager/knot_resolver_manager/datamodel/cache_schema.py +++ b/manager/knot_resolver_manager/datamodel/cache_schema.py @@ -21,7 +21,7 @@ class PrefillSchema(SchemaNode): ca_file: Optional[CheckedPath] = None def _validate(self) -> None: - if self.origin != ".": + if str(self.origin) != ".": raise ValueError("cache prefilling is not yet supported for non-root zones") diff --git a/manager/knot_resolver_manager/datamodel/types/types.py b/manager/knot_resolver_manager/datamodel/types/types.py index 185924e3a..42f829631 100644 --- a/manager/knot_resolver_manager/datamodel/types/types.py +++ b/manager/knot_resolver_manager/datamodel/types/types.py @@ -60,20 +60,22 @@ class DomainName(StrBase): Fully or partially qualified domain name. """ + _punycode: str _re = re.compile( r"(?=^.{,253}\.?$)" # max 253 chars - r"^(?!\.)" # do not start name with dot + r"(^(?!\.)" # do not start name with dot r"((?!-)" # do not start label with hyphen r"\.?[a-zA-Z0-9-]{,62}" # max 63 chars in label r"[a-zA-Z0-9])+" # do not end label with hyphen - r"\.?$" # end with or without '.' + r"\.?$)" # end with or without '.' + r"|^\.$" # allow root-zone ) def __init__(self, source_value: Any, object_path: str = "/") -> None: super().__init__(source_value) if isinstance(source_value, str): try: - punycode = source_value.encode("idna").decode("utf-8") + punycode = source_value.encode("idna").decode("utf-8") if source_value != "." else "." except ValueError: raise SchemaException( f"conversion of '{source_value}' to IDN punycode representation failed", @@ -82,6 +84,7 @@ class DomainName(StrBase): if type(self)._re.match(punycode): self._value = source_value + self._punycode = punycode else: raise SchemaException( f"'{source_value}' represented in punycode '{punycode}' does not match '{self._re.pattern}' pattern", @@ -100,7 +103,7 @@ class DomainName(StrBase): return hash(f"{self._value}.") def punycode(self) -> str: - return self._value.encode("idna").decode("utf-8") + return self._punycode @classmethod def json_schema(cls: Type["DomainName"]) -> Dict[Any, Any]: diff --git a/manager/tests/unit/datamodel/types/test_custom_types.py b/manager/tests/unit/datamodel/types/test_custom_types.py index 4980a5f57..a18910c8a 100644 --- a/manager/tests/unit/datamodel/types/test_custom_types.py +++ b/manager/tests/unit/datamodel/types/test_custom_types.py @@ -94,6 +94,7 @@ def test_checked_path(): @pytest.mark.parametrize( "val", [ + ".", "example.com", "this.is.example.com.", "test.example.com", @@ -108,7 +109,7 @@ def test_domain_name_valid(val: str): o = DomainName(val) assert str(o) == val assert o == DomainName(val) - assert o.punycode() == val.encode("idna").decode("utf-8") + assert o.punycode() == val.encode("idna").decode("utf-8") if val != "." else "." @pytest.mark.parametrize(