added config for virtual phone number
This commit is contained in:
parent
aa2fc45bdd
commit
1eaa06d961
10 changed files with 268 additions and 31 deletions
|
|
@ -3,6 +3,7 @@ package account
|
|||
import (
|
||||
"context"
|
||||
"crypto/rand"
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
|
@ -242,14 +243,18 @@ func (s *Service) phoneChangeCaller(ctx context.Context, userID int64, authKeyID
|
|||
// collision-retry loop so a store failure can't spin forever.
|
||||
const maxEmailSignupPhoneAttempts = 20
|
||||
|
||||
// assignEmailSignupDisplayPhone generates a short "888" display number for
|
||||
// an email-signup account rebinding to a new email (see
|
||||
// assignEmailSignupDisplayPhone generates a short display number for an
|
||||
// email-signup account rebinding to a new email (see
|
||||
// domain.NewEmailSignupDisplayPhone / auth.Service's SignUp counterpart),
|
||||
// re-rolling on the astronomically unlikely collision with an existing
|
||||
// account's phone.
|
||||
func (s *Service) assignEmailSignupDisplayPhone(ctx context.Context) (string, error) {
|
||||
prefix, err := randomEmailSignupPhonePrefix(s.emailSignupPhonePrefixes)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
for i := 0; i < maxEmailSignupPhoneAttempts; i++ {
|
||||
candidate, err := domain.NewEmailSignupDisplayPhone()
|
||||
candidate, err := domain.NewEmailSignupDisplayPhone(prefix)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
|
@ -262,6 +267,25 @@ func (s *Service) assignEmailSignupDisplayPhone(ctx context.Context) (string, er
|
|||
return "", fmt.Errorf("assign email signup display phone: exhausted %d attempts", maxEmailSignupPhoneAttempts)
|
||||
}
|
||||
|
||||
// randomEmailSignupPhonePrefix mirrors auth.Service's identical helper
|
||||
// (unexported to each package, but must pick with the same fairness): pick
|
||||
// one entry at random from prefixes, falling back to domain.EmailPhonePrefix
|
||||
// ("888") when the list is empty.
|
||||
func randomEmailSignupPhonePrefix(prefixes []string) (string, error) {
|
||||
if len(prefixes) == 0 {
|
||||
return domain.EmailPhonePrefix, nil
|
||||
}
|
||||
if len(prefixes) == 1 {
|
||||
return prefixes[0], nil
|
||||
}
|
||||
var b [8]byte
|
||||
if _, err := rand.Read(b[:]); err != nil {
|
||||
return "", fmt.Errorf("pick email signup phone prefix: %w", err)
|
||||
}
|
||||
idx := binary.LittleEndian.Uint64(b[:]) % uint64(len(prefixes))
|
||||
return prefixes[idx], nil
|
||||
}
|
||||
|
||||
func phoneChangeHash() (string, error) {
|
||||
var raw [8]byte
|
||||
if _, err := rand.Read(raw[:]); err != nil {
|
||||
|
|
|
|||
|
|
@ -55,6 +55,10 @@ type Service struct {
|
|||
// 验证码走 loginEmailSender 发到解码出的邮箱;非 888 号码一律拒绝——本服务器没有真实
|
||||
// 短信通道,放行会让账号的邮箱身份绑定被绕过(见迁移前的密码找回验证码漏洞教训)。
|
||||
emailSignupEnabled bool
|
||||
// emailSignupPhonePrefixes 是改绑邮箱时随机挑选的账号展示号码号段前缀
|
||||
// 列表(domain.NewEmailSignupDisplayPhone),与 auth.Service 的同名字段
|
||||
// 同一份服务端配置来源。为空时退回默认 "888"。
|
||||
emailSignupPhonePrefixes []string
|
||||
}
|
||||
|
||||
// ServiceOption 调整 account 服务依赖。
|
||||
|
|
@ -163,6 +167,14 @@ func WithEmailSignup(enabled bool) ServiceOption {
|
|||
}
|
||||
}
|
||||
|
||||
// WithEmailSignupPhonePrefixes 设置改绑邮箱时展示号码随机挑选的号段前缀列表
|
||||
// (见 emailSignupPhonePrefixes 字段注释)。
|
||||
func WithEmailSignupPhonePrefixes(prefixes []string) ServiceOption {
|
||||
return func(s *Service) {
|
||||
s.emailSignupPhonePrefixes = prefixes
|
||||
}
|
||||
}
|
||||
|
||||
// NewService 创建 account 服务。
|
||||
func NewService(passwords store.PasswordStore, opts ...ServiceOption) *Service {
|
||||
s := &Service{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue