6
6
"net/netip"
7
7
"regexp"
8
8
"strings"
9
+ "unicode"
9
10
10
11
"go4.org/netipx"
11
12
"tailscale.com/util/dnsname"
@@ -20,10 +21,40 @@ const (
20
21
LabelHostnameLength = 63
21
22
)
22
23
24
+ var invalidDNSRegex = regexp .MustCompile ("[^a-z0-9-.]+" )
23
25
var invalidCharsInUserRegex = regexp .MustCompile ("[^a-z0-9-.]+" )
24
26
25
27
var ErrInvalidUserName = errors .New ("invalid user name" )
26
28
29
+ func ValidateUsername (username string ) error {
30
+ // Ensure the username meets the minimum length requirement
31
+ if len (username ) < 2 {
32
+ return errors .New ("username must be at least 2 characters long" )
33
+ }
34
+
35
+ // Ensure the username does not start with a number
36
+ if unicode .IsDigit (rune (username [0 ])) {
37
+ return errors .New ("username cannot start with a number" )
38
+ }
39
+
40
+ atCount := 0
41
+ for _ , char := range username {
42
+ switch {
43
+ case unicode .IsLetter (char ), unicode .IsDigit (char ), char == '-' :
44
+ // Valid characters
45
+ case char == '@' :
46
+ atCount ++
47
+ if atCount > 1 {
48
+ return errors .New ("username cannot contain more than one '@'" )
49
+ }
50
+ default :
51
+ return fmt .Errorf ("username contains invalid character: '%c'" , char )
52
+ }
53
+ }
54
+
55
+ return nil
56
+ }
57
+
27
58
func CheckForFQDNRules (name string ) error {
28
59
if len (name ) > LabelHostnameLength {
29
60
return fmt .Errorf (
@@ -39,7 +70,7 @@ func CheckForFQDNRules(name string) error {
39
70
ErrInvalidUserName ,
40
71
)
41
72
}
42
- if invalidCharsInUserRegex .MatchString (name ) {
73
+ if invalidDNSRegex .MatchString (name ) {
43
74
return fmt .Errorf (
44
75
"DNS segment should only be composed of lowercase ASCII letters numbers, hyphen and dots. %v doesn't comply with theses rules: %w" ,
45
76
name ,
@@ -52,7 +83,7 @@ func CheckForFQDNRules(name string) error {
52
83
53
84
func ConvertWithFQDNRules (name string ) string {
54
85
name = strings .ToLower (name )
55
- name = invalidCharsInUserRegex .ReplaceAllString (name , "" )
86
+ name = invalidDNSRegex .ReplaceAllString (name , "" )
56
87
57
88
return name
58
89
}
@@ -197,7 +228,7 @@ func NormalizeToFQDNRules(name string, stripEmailDomain bool) (string, error) {
197
228
} else {
198
229
name = strings .ReplaceAll (name , "@" , "." )
199
230
}
200
- name = invalidCharsInUserRegex .ReplaceAllString (name , "-" )
231
+ name = invalidDNSRegex .ReplaceAllString (name , "-" )
201
232
202
233
for _ , elt := range strings .Split (name , "." ) {
203
234
if len (elt ) > LabelHostnameLength {
0 commit comments