From 7f1780ad2df1a21a7cffd863959670d9351afdd2 Mon Sep 17 00:00:00 2001 From: catborise Date: Mon, 19 Oct 2026 20:28:29 +0300 Subject: [PATCH] fix(networks): the fixed-address dialogs take real MAC addresses and host names The MAC field's pattern ([0-9/:]+) had no hex letters, so the browser refused nearly every MAC address (52:54:00:ab:cd:ef) and no IPv4 fixed address could be added from the page. The host name field of both dialogs ([a-zA-Z0-9_]+) refused names such as web-01 or db.lan. The MAC takes hex digits and ":", the name letters, digits, "_", "." and "-"; the server already escapes both into the network XML. --- .../templates/modify_ipv4_fixed_address.html | 4 +-- .../templates/modify_ipv6_fixed_address.html | 2 +- networks/tests/__init__.py | 0 networks/tests/test_fixed_address_form.py | 31 +++++++++++++++++++ 4 files changed, 34 insertions(+), 3 deletions(-) create mode 100644 networks/tests/__init__.py create mode 100644 networks/tests/test_fixed_address_form.py diff --git a/networks/templates/modify_ipv4_fixed_address.html b/networks/templates/modify_ipv4_fixed_address.html index 05bf1ff9..4886e0bc 100644 --- a/networks/templates/modify_ipv4_fixed_address.html +++ b/networks/templates/modify_ipv4_fixed_address.html @@ -24,13 +24,13 @@
- +
- +
diff --git a/networks/templates/modify_ipv6_fixed_address.html b/networks/templates/modify_ipv6_fixed_address.html index e5439bda..4ca340bc 100644 --- a/networks/templates/modify_ipv6_fixed_address.html +++ b/networks/templates/modify_ipv6_fixed_address.html @@ -30,7 +30,7 @@
- +
diff --git a/networks/tests/__init__.py b/networks/tests/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/networks/tests/test_fixed_address_form.py b/networks/tests/test_fixed_address_form.py new file mode 100644 index 00000000..3f92317a --- /dev/null +++ b/networks/tests/test_fixed_address_form.py @@ -0,0 +1,31 @@ +"""The fixed-address dialogs take real MAC addresses and host names: the +browser refuses what their pattern attributes do not match.""" + +import re +from types import SimpleNamespace + +from django.template.loader import render_to_string +from django.test import SimpleTestCase +from lxml import html + + +def pattern(template, name): + superuser = SimpleNamespace(user=SimpleNamespace(is_superuser=True)) + page = html.fromstring(render_to_string(template, {"request": superuser})) + return re.compile(page.xpath(f"//input[@name='{name}']/@pattern")[0]) + + +class FixedAddressFormTests(SimpleTestCase): + def test_macs_and_host_names_are_accepted(self): + mac = pattern("modify_ipv4_fixed_address.html", "mac") + for value in ("52:54:00:ab:cd:ef", "52:54:00:AB:CD:EF"): + with self.subTest(mac=value): + self.assertTrue(mac.fullmatch(value)) + for template in ("modify_ipv4_fixed_address.html", "modify_ipv6_fixed_address.html"): + name = pattern(template, "name") + for value in ("web-01", "db.lan", "vm_1"): + with self.subTest(template=template, name=value): + self.assertTrue(name.fullmatch(value)) + for value in ("a b", 'x"<'): + with self.subTest(template=template, refused=value): + self.assertFalse(name.fullmatch(value))