Coverage for seedboxsync/front/forms/validators/validators.py: 86%
21 statements
« prev ^ index » next coverage.py v7.16.1, created at 2026-09-26 17:14 +0000
« prev ^ index » next coverage.py v7.16.1, created at 2026-09-26 17:14 +0000
1#
2# Copyright (C) 2015-2026 Guillaume Kulakowski <guillaume@kulakowski.fr>
3#
4# For the full copyright and license information, please view the LICENSE
5# file that was distributed with this source code.
6#
7"""SeedboxSync WTForms domain or IP validator."""
9from ipaddress import ip_address
10import re
11from wtforms import ValidationError
13# Python-compatible regex to validate domain names without variable-width lookbehinds.
14DOMAIN_REGEX = re.compile(r"^(?:(?!-)[A-Za-z0-9-]{0,61}[A-Za-z0-9]\.)+[A-Za-z]{2,}$")
17class DomainOrIP:
18 """WTForms validator accepting either a valid domain name or an IP address."""
20 def __init__(self, message: str | None = None) -> None:
21 """Initialize the DomainOrIP validator.
23 Args:
24 message: Custom validation error message. If not provided,
25 a default error message will be used.
26 """
27 if not message:
28 message = "Value must be a valid domain name or IP address."
29 self.message = message
31 def __call__(self, form: object, field: object) -> None:
32 """Validate the input field content.
34 Args:
35 form: The WTForms form instance being validated.
36 field: The field containing the data to validate.
38 Raises:
39 ValidationError: If the value is neither a valid IP address
40 nor a valid domain name.
41 """
42 value = getattr(field, "data", "")
44 if not value:
45 return # Let DataRequired/Optional handle empty fields
47 # 1. Check if input is a valid IP address (IPv4 or IPv6)
48 try:
49 ip_address(value)
50 except ValueError:
51 pass
52 else:
53 return # Valid IP address
55 # 2. Check if input is a valid domain name
56 if DOMAIN_REGEX.match(value):
57 return # Valid domain name
59 # 3. Raise validation error if both checks fail
60 raise ValidationError(self.message)