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  }