github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/libkb/checkers.go (about) 1 // Copyright 2015 Keybase, Inc. All rights reserved. Use of 2 // this source code is governed by the included BSD license. 3 4 package libkb 5 6 import ( 7 "fmt" 8 "regexp" 9 "strings" 10 "unicode" 11 12 "github.com/keybase/client/go/kbun" 13 ) 14 15 var emailRE = regexp.MustCompile(`^\S+@\S+\.\S+$`) 16 17 // Also used in shared/signup/device-name/index.tsx 18 var deviceRE = regexp.MustCompile(`^[a-zA-Z0-9][ _'a-zA-Z0-9+‘’—–-]*$`) 19 var badDeviceRE = regexp.MustCompile(` |[ '_-]$|['_-][ ]?['_-]`) 20 var normalizeDeviceRE = regexp.MustCompile(`[^a-zA-Z0-9]`) 21 22 var CheckEmail = Checker{ 23 F: func(s string) bool { 24 return len(s) > 3 && emailRE.MatchString(s) 25 }, 26 Hint: "must be a valid email address", 27 } 28 29 var CheckUsername = Checker{ 30 F: kbun.CheckUsername, 31 Hint: "between 2 and 16 characters long", 32 } 33 34 var CheckEmailOrUsername = Checker{ 35 F: func(s string) bool { 36 return CheckEmail.F(s) || CheckUsername.F(s) 37 }, 38 Hint: "valid usernames are 2-16 letters long", 39 } 40 41 var CheckPassphraseSimple = Checker{ 42 F: func(s string) bool { 43 return len(s) > 0 44 }, 45 Hint: "passphrase cannot be empty", 46 } 47 48 var CheckPassphraseNew = Checker{ 49 F: func(s string) bool { 50 r := []rune(s) 51 if len(r) > 0 && unicode.IsSpace(r[0]) { 52 return false 53 } 54 return len(s) >= MinPassphraseLength 55 }, 56 Hint: fmt.Sprintf("passphrase must be %d or more characters", MinPassphraseLength), 57 PreserveSpace: true, 58 } 59 60 var CheckInviteCode = Checker{ 61 F: func(s string) bool { 62 return len(s) > 4 63 }, 64 Hint: "Invite codes are 4 or more characters", 65 } 66 67 func normalizeDeviceName(s string) string { 68 return strings.ToLower(normalizeDeviceRE.ReplaceAllString(s, "")) 69 } 70 71 var CheckDeviceName = Checker{ 72 F: func(s string) bool { 73 normalized := normalizeDeviceName(s) 74 75 return len(normalized) >= 3 && 76 len(normalized) <= 64 && 77 deviceRE.MatchString(s) && 78 !badDeviceRE.MatchString(s) 79 }, 80 Transform: func(s string) string { 81 s = strings.ReplaceAll(s, "—", "-") // em dash 82 s = strings.ReplaceAll(s, "–", "-") // en dash 83 s = strings.ReplaceAll(s, "‘", "'") // curly quote #1 84 s = strings.ReplaceAll(s, "’", "'") // curly quote #2 85 return s 86 }, 87 Normalize: normalizeDeviceName, 88 Hint: "between 3 and 64 characters long; use a-Z, 0-9, space, plus, underscore, dash and apostrophe", 89 } 90 91 func MakeCheckKex2SecretPhrase(g *GlobalContext) Checker { 92 return Checker{ 93 F: func(s string) bool { 94 if err := validPhrase(s, []int{Kex2PhraseEntropy, Kex2PhraseEntropy2}); err != nil { 95 g.Log.Debug("invalid kex2 phrase: %s", err) 96 return false 97 } 98 return true 99 }, 100 Hint: "Wrong secret phrase. Please try again.", 101 } 102 } 103 104 func IsYes(s string) bool { 105 s = strings.ToLower(strings.TrimSpace(s)) 106 return s == "y" || s == "yes" 107 } 108 109 func IsEmpty(s string) bool { 110 return len(strings.TrimSpace(s)) == 0 111 } 112 113 func IsNo(s string) bool { 114 s = strings.ToLower(strings.TrimSpace(s)) 115 return s == "n" || s == "no" 116 } 117 118 var CheckYesNo = Checker{ 119 F: func(s string) bool { 120 return IsYes(s) || IsNo(s) 121 }, 122 Hint: "'yes' or 'no'", 123 } 124 125 var CheckNotEmpty = Checker{ 126 F: func(s string) bool { 127 return len(s) > 0 128 }, 129 Hint: "cannot be empty", 130 } 131 132 type CheckMember struct { 133 Set []string 134 } 135 136 func (c CheckMember) Checker() Checker { 137 return Checker{ 138 F: func(s string) bool { 139 for _, v := range c.Set { 140 if Cicmp(v, s) { 141 return true 142 } 143 } 144 return false 145 }, 146 Hint: strings.Join(c.Set, ", "), 147 } 148 }