fix: allow dot character in entity names for UI and backend validation

Bulk import accepted dots in frontend/backend/server names but UI and
backend validators rejected them with ^[a-zA-Z0-9_-]+$. After import,
entities with dots could not be edited. HAProxy itself allows dots in
section names, so the regex is expanded to ^[a-zA-Z0-9_.-]+$ across
all 12 validation points (5 React form rules, 1 ACL char-strip,
3 Pydantic validators, 1 WAF validator, 2 config-validator warnings).
This commit is contained in:
taylanbakircioglu
2026-04-14 01:26:03 +03:00
parent 7fffaddaf8
commit 71c717364c
8 changed files with 17 additions and 17 deletions
+5 -5
View File
@@ -108,8 +108,8 @@ class FrontendConfig(BaseModel):
raise ValueError('Frontend name cannot be empty')
# HAProxy names cannot contain spaces or special characters
if not re.match(r'^[a-zA-Z0-9_-]+$', v.strip()):
raise ValueError('Frontend name can only contain letters, numbers, underscore (_) and dash (-). Spaces and special characters are not allowed.')
if not re.match(r'^[a-zA-Z0-9_.-]+$', v.strip()):
raise ValueError('Frontend name can only contain letters, numbers, dot (.), underscore (_) and dash (-). Spaces and special characters are not allowed.')
if len(v.strip()) > 50:
raise ValueError('Frontend name cannot exceed 50 characters')
@@ -147,8 +147,8 @@ class FrontendConfig(BaseModel):
@validator('default_backend')
def validate_default_backend(cls, v):
if v and not re.match(r'^[a-zA-Z0-9_-]+$', v.strip()):
raise ValueError('Default backend name can only contain letters, numbers, underscore (_) and dash (-)')
if v and not re.match(r'^[a-zA-Z0-9_.-]+$', v.strip()):
raise ValueError('Default backend name can only contain letters, numbers, dot (.), underscore (_) and dash (-)')
return v.strip() if v else None
@validator('ssl_certificate_id')
@@ -288,7 +288,7 @@ class FrontendConfig(BaseModel):
continue
# Basic ACL syntax validation
if not re.match(r'^[a-zA-Z0-9_-]+\s+', rule):
if not re.match(r'^[a-zA-Z0-9_.-]+\s+', rule):
raise ValueError(f'Invalid ACL rule syntax: "{rule}". Must start with ACL name followed by condition.')
# Check for dangerous patterns
+2 -2
View File
@@ -22,8 +22,8 @@ class WAFRule(BaseModel):
raise ValueError('WAF rule name cannot be empty')
# HAProxy ACL names cannot contain spaces or special characters
if not re.match(r'^[a-zA-Z0-9_-]+$', v.strip()):
raise ValueError('WAF rule name can only contain letters, numbers, underscore (_) and dash (-). Spaces and special characters are not allowed.')
if not re.match(r'^[a-zA-Z0-9_.-]+$', v.strip()):
raise ValueError('WAF rule name can only contain letters, numbers, dot (.), underscore (_) and dash (-). Spaces and special characters are not allowed.')
if len(v.strip()) > 50:
raise ValueError('WAF rule name cannot exceed 50 characters')
+4 -4
View File
@@ -156,11 +156,11 @@ class HAProxyConfigValidator:
section_name = parts[1]
# Check name format
if not re.match(r'^[a-zA-Z0-9_-]+$', section_name):
if not re.match(r'^[a-zA-Z0-9_.-]+$', section_name):
self._add_result(
ValidationLevel.WARNING,
f"Section name '{section_name}' contains invalid characters",
suggestion="Use only letters, numbers, underscore and hyphen"
suggestion="Use only letters, numbers, dot, underscore and hyphen"
)
# Set current section for validation
@@ -265,12 +265,12 @@ class HAProxyConfigValidator:
server_addr = args[1]
# Check server name format
if not re.match(r'^[a-zA-Z0-9_-]+$', server_name):
if not re.match(r'^[a-zA-Z0-9_.-]+$', server_name):
self._add_result(
ValidationLevel.WARNING,
f"Server name '{server_name}' contains invalid characters",
directive="server",
suggestion="Use only letters, numbers, underscore and hyphen"
suggestion="Use only letters, numbers, dot, underscore and hyphen"
)
# Check address format
+1 -1
View File
@@ -313,7 +313,7 @@ function ACLDefinitionCard({ rule, index, onChange, onDelete }) {
<Col flex="140px">
<Input
value={rule.name}
onChange={(e) => onChange(index, { ...rule, name: e.target.value.replace(/[^a-zA-Z0-9_-]/g, '') })}
onChange={(e) => onChange(index, { ...rule, name: e.target.value.replace(/[^a-zA-Z0-9_.-]/g, '') })}
placeholder="acl_name"
size="small"
addonBefore={<FilterOutlined style={{ fontSize: 11 }} />}
+2 -2
View File
@@ -1646,7 +1646,7 @@ const BackendServers = () => {
label="Backend Name"
rules={[
{ required: true, message: 'Please enter backend name' },
{ pattern: /^[a-zA-Z0-9_-]+$/, message: 'Only alphanumeric, underscore and dash allowed' }
{ pattern: /^[a-zA-Z0-9_.-]+$/, message: 'Only alphanumeric, dot, underscore and dash allowed' }
]}
>
<Input placeholder="e.g., web_servers" />
@@ -1939,7 +1939,7 @@ const BackendServers = () => {
label="Server Name"
rules={[
{ required: true, message: 'Please enter server name' },
{ pattern: /^[a-zA-Z0-9_-]+$/, message: 'Only alphanumeric, underscore and dash allowed' }
{ pattern: /^[a-zA-Z0-9_.-]+$/, message: 'Only alphanumeric, dot, underscore and dash allowed' }
]}
>
<Input placeholder="e.g., web1" />
@@ -1381,7 +1381,7 @@ const FrontendManagement = () => {
extra="Unique identifier for this frontend"
rules={[
{ required: true, message: 'Please enter frontend name' },
{ pattern: /^[a-zA-Z0-9_-]+$/, message: 'Only alphanumeric, underscore and dash allowed' }
{ pattern: /^[a-zA-Z0-9_.-]+$/, message: 'Only alphanumeric, dot, underscore and dash allowed' }
]}
>
<Input placeholder="e.g., main_frontend" />
+1 -1
View File
@@ -934,7 +934,7 @@ const SSLManagement = () => {
label="Certificate Name"
rules={[
{ required: true, message: 'Please enter certificate name' },
{ pattern: /^[a-zA-Z0-9_-]+$/, message: 'Only alphanumeric, underscore and dash allowed' }
{ pattern: /^[a-zA-Z0-9_.-]+$/, message: 'Only alphanumeric, dot, underscore and dash allowed' }
]}
extra={selectedCertificate && selectedCertificate.id ? "Certificate name cannot be changed (used as file path on servers)" : "Used as file path: /etc/ssl/haproxy/{name}.pem"}
tooltip={selectedCertificate && selectedCertificate.id ? "Certificate name is immutable after creation to maintain file system references" : null}
+1 -1
View File
@@ -1442,7 +1442,7 @@ const WAFManagement = () => {
label="Rule Name"
rules={[
{ required: true, message: 'Please enter rule name' },
{ pattern: /^[a-zA-Z0-9_-]+$/, message: 'Only alphanumeric, underscore and dash allowed' }
{ pattern: /^[a-zA-Z0-9_.-]+$/, message: 'Only alphanumeric, dot, underscore and dash allowed' }
]}
>
<Input placeholder="e.g., api_rate_limit" />