Files
wg-admin/internal/validation/client.go
Calmcacil 26120b8bc2 Add WireGuard TUI implementation
- Add Go TUI with bubbletea for WireGuard management
- Implement client CRUD operations with QR code generation
- Add configuration and validation modules
- Install/update scripts for client setup
- Update Makefile to build binaries to bin/ directory
- Add .gitignore for Go projects
2026-01-12 19:03:35 +01:00

87 lines
2.3 KiB
Go

package validation
import (
"fmt"
"regexp"
"strings"
)
// ValidateClientName validates the client name format
// Requirements: alphanumeric, hyphens, underscores only, max 64 characters
func ValidateClientName(name string) error {
if name == "" {
return fmt.Errorf("client name cannot be empty")
}
if len(name) > 64 {
return fmt.Errorf("client name must be 64 characters or less (got %d)", len(name))
}
// Check for valid characters: a-z, A-Z, 0-9, hyphen, underscore
matched, err := regexp.MatchString(`^[a-zA-Z0-9_-]+$`, name)
if err != nil {
return fmt.Errorf("failed to validate client name: %w", err)
}
if !matched {
return fmt.Errorf("client name contains invalid characters (allowed: a-z, A-Z, 0-9, -, _)")
}
return nil
}
// ValidateIPAvailability checks if an IP address is already assigned to a client
// This function is meant to be called after getting next available IPs
func ValidateIPAvailability(ipv4, ipv6 string, existingIPs map[string]bool) error {
if ipv4 != "" && existingIPs[ipv4] {
return fmt.Errorf("IPv4 address %s is already assigned", ipv4)
}
if ipv6 != "" && existingIPs[ipv6] {
return fmt.Errorf("IPv6 address %s is already assigned", ipv6)
}
return nil
}
// ValidateDNSServers validates DNS server addresses
// Requirements: comma-separated list of IPv4 addresses
func ValidateDNSServers(dns string) error {
if dns == "" {
return fmt.Errorf("DNS servers cannot be empty")
}
// Split by comma and trim whitespace
servers := strings.Split(dns, ",")
for _, server := range servers {
server = strings.TrimSpace(server)
if server == "" {
continue
}
// Basic IPv4 validation (4 octets, each 0-255)
matched, err := regexp.MatchString(`^(\d{1,3}\.){3}\d{1,3}$`, server)
if err != nil {
return fmt.Errorf("failed to validate DNS server: %w", err)
}
if !matched {
return fmt.Errorf("invalid DNS server format: %s (expected IPv4 address)", server)
}
// Validate each octet is in range 0-255
parts := strings.Split(server, ".")
for _, part := range parts {
var num int
if _, err := fmt.Sscanf(part, "%d", &num); err != nil {
return fmt.Errorf("invalid DNS server: %s", server)
}
if num < 0 || num > 255 {
return fmt.Errorf("DNS server octet out of range (0-255) in: %s", server)
}
}
}
return nil
}