- 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
87 lines
2.3 KiB
Go
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
|
|
}
|