added config for virtual phone number
This commit is contained in:
parent
aa2fc45bdd
commit
1eaa06d961
10 changed files with 268 additions and 31 deletions
|
|
@ -139,33 +139,53 @@ func NormalizeEmailForPhone(email string) string {
|
|||
return strings.ToLower(strings.TrimSpace(email))
|
||||
}
|
||||
|
||||
// emailSignupDisplayPhoneDigits is how many random digits follow the "888"
|
||||
// prefix in a NewEmailSignupDisplayPhone result, e.g. "888" + 8 digits =
|
||||
// emailSignupDisplayPhoneDigits is how many random digits follow the prefix
|
||||
// in a NewEmailSignupDisplayPhone result, e.g. prefix "888" + 8 digits =
|
||||
// "88812345678" (formats on-screen as something like "+888 1234 5678").
|
||||
const emailSignupDisplayPhoneDigits = 8
|
||||
|
||||
// NewEmailSignupDisplayPhone generates a short, all-digit "888" phone number
|
||||
// for an email-signup account's users.phone column. Unlike EncodeEmailPhone
|
||||
// this carries no information about the email — it is purely a
|
||||
// normal-looking display/identity number — so the caller must separately
|
||||
// persist the email->user association (see User.SignupEmail) for returning
|
||||
// logins to be found. Because the result is all digits, IsEmailSignupPhone
|
||||
// on it is always false: once assigned, it behaves exactly like a real phone
|
||||
// number everywhere else in the system (contacts, search, ByPhone lookups).
|
||||
func NewEmailSignupDisplayPhone() (string, error) {
|
||||
// NewEmailSignupDisplayPhone generates a short, all-digit phone number for an
|
||||
// email-signup account's users.phone column, using the given prefix (one of
|
||||
// the server's configured EmailSignupPhonePrefixes — see
|
||||
// help.getAppConfig's email_signup_phone_prefixes, config.go). This is
|
||||
// unrelated to EncodeEmailPhone's own fixed "888" wire prefix: that one only
|
||||
// ever travels internally between client and server during sendCode/signIn
|
||||
// and is never shown to anyone, so it has no reason to be configurable,
|
||||
// unlike this display number, which is the account's actual, permanent,
|
||||
// user-visible phone. The caller must separately persist the email->user
|
||||
// association (see User.SignupEmail) for returning logins to be found.
|
||||
// Because the result is all digits, IsEmailSignupPhone on it is always
|
||||
// false: once assigned, it behaves exactly like a real phone number
|
||||
// everywhere else in the system (contacts, search, ByPhone lookups).
|
||||
func NewEmailSignupDisplayPhone(prefix string) (string, error) {
|
||||
if !isAllASCIIDigits(prefix) {
|
||||
return "", fmt.Errorf("email signup display phone prefix %q must be non-empty digits", prefix)
|
||||
}
|
||||
b := make([]byte, emailSignupDisplayPhoneDigits)
|
||||
if _, err := rand.Read(b); err != nil {
|
||||
return "", fmt.Errorf("generate email signup display phone: %w", err)
|
||||
}
|
||||
var out strings.Builder
|
||||
out.Grow(len(EmailPhonePrefix) + emailSignupDisplayPhoneDigits)
|
||||
out.WriteString(EmailPhonePrefix)
|
||||
out.Grow(len(prefix) + emailSignupDisplayPhoneDigits)
|
||||
out.WriteString(prefix)
|
||||
for _, v := range b {
|
||||
out.WriteByte('0' + v%10)
|
||||
}
|
||||
return out.String(), nil
|
||||
}
|
||||
|
||||
func isAllASCIIDigits(s string) bool {
|
||||
if s == "" {
|
||||
return false
|
||||
}
|
||||
for _, r := range s {
|
||||
if r < '0' || r > '9' {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// IsEmailSignupPhone reports whether phone was produced by EncodeEmailPhone.
|
||||
// Every encoded value contains at least one letter (the mandatory '@'
|
||||
// escape's 'q' marker byte), which real, all-digit phone numbers — even
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ func TestDecodeEmailPhoneRejectsNonEmailNumbers(t *testing.T) {
|
|||
func TestNewEmailSignupDisplayPhoneLooksLikeARealPhoneNumber(t *testing.T) {
|
||||
seen := make(map[string]struct{})
|
||||
for i := 0; i < 200; i++ {
|
||||
phone, err := NewEmailSignupDisplayPhone()
|
||||
phone, err := NewEmailSignupDisplayPhone(EmailPhonePrefix)
|
||||
if err != nil {
|
||||
t.Fatalf("NewEmailSignupDisplayPhone: %v", err)
|
||||
}
|
||||
|
|
@ -94,3 +94,26 @@ func TestNewEmailSignupDisplayPhoneLooksLikeARealPhoneNumber(t *testing.T) {
|
|||
t.Fatalf("only %d distinct values out of 200 draws, generator looks non-random", len(seen))
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewEmailSignupDisplayPhoneHonorsConfiguredPrefix(t *testing.T) {
|
||||
for _, prefix := range []string{"380", "1", "7777"} {
|
||||
phone, err := NewEmailSignupDisplayPhone(prefix)
|
||||
if err != nil {
|
||||
t.Fatalf("NewEmailSignupDisplayPhone(%q): %v", prefix, err)
|
||||
}
|
||||
if !strings.HasPrefix(phone, prefix) {
|
||||
t.Fatalf("phone %q missing configured prefix %q", phone, prefix)
|
||||
}
|
||||
if !ValidPhone(phone) {
|
||||
t.Fatalf("phone %q fails ValidPhone", phone)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewEmailSignupDisplayPhoneRejectsInvalidPrefix(t *testing.T) {
|
||||
for _, prefix := range []string{"", "abc", "88q", "-1"} {
|
||||
if _, err := NewEmailSignupDisplayPhone(prefix); err == nil {
|
||||
t.Fatalf("NewEmailSignupDisplayPhone(%q) err = nil, want error", prefix)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue